2022-08-02 14:04:25 +00:00
|
|
|
/*
|
|
|
|
* BIRD -- Simple Network Management Protocol (SNMP)
|
|
|
|
*
|
|
|
|
* (c) 2022 Vojtech Vilimek <vojtech.vilimek@nic.cz>
|
|
|
|
* (c) 2022 CZ.NIC z.s.p.o
|
|
|
|
*
|
|
|
|
* Can be freely distributed and used under the terms of the GNU GPL.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2022-08-10 15:31:32 +00:00
|
|
|
#include "lib/unaligned.h"
|
|
|
|
#include "subagent.h"
|
2024-05-24 13:20:30 +00:00
|
|
|
#include "mib_tree.h"
|
2022-11-15 15:29:03 +00:00
|
|
|
#include "snmp_utils.h"
|
2024-05-24 13:20:30 +00:00
|
|
|
#include "bgp4_mib.h"
|
2022-08-02 14:04:25 +00:00
|
|
|
|
2024-07-22 16:17:16 +00:00
|
|
|
/*
|
|
|
|
* Goals:
|
|
|
|
* In current situation, we do not handle the dynamic BGP case.
|
2022-09-06 16:04:29 +00:00
|
|
|
*/
|
|
|
|
|
2023-11-08 09:55:42 +00:00
|
|
|
/**
|
2023-11-16 06:11:14 +00:00
|
|
|
*
|
2023-11-08 09:55:42 +00:00
|
|
|
* Handling of malformed packet:
|
|
|
|
*
|
2023-11-16 06:11:14 +00:00
|
|
|
* 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 implicitly 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.
|
2024-01-10 11:21:46 +00:00
|
|
|
* In SNMP_RESET state we skip all received bytes and wait for snmp_tx_skip()
|
2023-11-16 06:11:14 +00:00
|
|
|
* to be called. The socket's tx_hook is called when the TX-buffer is empty,
|
|
|
|
* meaning our response (agentx-Response-PDU) was send.
|
2023-11-15 14:03:55 +00:00
|
|
|
*
|
2023-11-16 06:11:14 +00:00
|
|
|
*
|
|
|
|
* Partial parsing:
|
|
|
|
*
|
|
|
|
* It may happen that we received only staring part of some PDU from the
|
|
|
|
* communication socket. In most cases, if we recognize this situation we
|
|
|
|
* immediately return, waiting for rest of the PDU to arrive. But for packets
|
|
|
|
* like agentx-Get-PDU, agentx-GetNext-PDU and agentx-GetBulk-PDU it could be
|
|
|
|
* costly as they could hold many VarBinds. We don't want to process these
|
|
|
|
* packet twice because it is a lot work. We parse all VarBinds until we hit the
|
|
|
|
* first incomplete one. The logic behind this is to release as much as
|
|
|
|
* possible space from receive buffer. When we hit the first incomplete VarBind,
|
|
|
|
* we store information about the parsing state and move the header inside the
|
|
|
|
* receive buffer.
|
2023-11-15 14:03:55 +00:00
|
|
|
*
|
|
|
|
* Transmit packet context
|
|
|
|
*
|
2023-11-08 09:55:42 +00:00
|
|
|
*/
|
|
|
|
|
2024-01-23 23:23:31 +00:00
|
|
|
static uint parse_response(struct snmp_proto *p, byte *buf);
|
|
|
|
static void do_response(struct snmp_proto *p, byte *buf);
|
|
|
|
static uint parse_gets_pdu(struct snmp_proto *p, byte *pkt);
|
2023-09-11 11:06:20 +00:00
|
|
|
static struct agentx_response *prepare_response(struct snmp_proto *p, struct snmp_pdu *c);
|
2024-01-10 11:21:46 +00:00
|
|
|
static void response_err_ind(struct snmp_proto *p, struct agentx_response *res, enum agentx_response_errs err, u16 ind);
|
2024-01-23 23:23:31 +00:00
|
|
|
static uint update_packet_size(struct agentx_header *start, byte *end);
|
2024-04-22 10:55:33 +00:00
|
|
|
|
2024-07-22 16:17:16 +00:00
|
|
|
/* standard SNMP internet prefix (.1.3.6.1) */
|
2024-04-22 10:55:33 +00:00
|
|
|
const u32 snmp_internet[] = { SNMP_ISO, SNMP_ORG, SNMP_DOD, SNMP_INTERNET };
|
2023-09-04 11:51:29 +00:00
|
|
|
|
2024-01-23 23:23:31 +00:00
|
|
|
/*
|
|
|
|
* snmp_header - store packet information into buffer
|
|
|
|
* @h: pointer to created packet header in TX-buffer
|
|
|
|
* @type: created PDU type
|
|
|
|
* @flags: set flags
|
|
|
|
*
|
|
|
|
* Payload length is set to zero legth. Padding is also zeroed. Real stored
|
|
|
|
* flags are dependent on compile-time message byte-order configuration.
|
|
|
|
*/
|
2023-11-15 11:37:10 +00:00
|
|
|
static inline void
|
|
|
|
snmp_header(struct agentx_header *h, enum agentx_pdu_types type, u8 flags)
|
|
|
|
{
|
|
|
|
STORE_U8(h->version, AGENTX_VERSION);
|
2024-01-23 23:23:31 +00:00
|
|
|
STORE_U8(h->type, type);
|
2023-11-15 11:37:10 +00:00
|
|
|
STORE_U8(h->flags, flags | SNMP_ORDER);
|
2024-01-23 23:23:31 +00:00
|
|
|
STORE_U8(h->reserved, 0);
|
2023-11-15 11:37:10 +00:00
|
|
|
STORE_U32(h->payload, 0);
|
|
|
|
}
|
|
|
|
|
2024-01-23 23:23:31 +00:00
|
|
|
/*
|
2024-07-24 11:38:36 +00:00
|
|
|
* snmp_blank_header - create header with no flags except byte order
|
2024-01-23 23:23:31 +00:00
|
|
|
* @h: pointer to created header in TX-buffer
|
|
|
|
* @type: create PDU type
|
|
|
|
*
|
|
|
|
* Only flag possibly set may be packet byte order configuration.
|
|
|
|
*/
|
2023-11-15 11:37:10 +00:00
|
|
|
static inline void
|
|
|
|
snmp_blank_header(struct agentx_header *h, enum agentx_pdu_types type)
|
|
|
|
{
|
2024-01-23 23:23:31 +00:00
|
|
|
snmp_header(h, type, (u8) 0);
|
2023-11-15 11:37:10 +00:00
|
|
|
}
|
2023-10-25 14:57:46 +00:00
|
|
|
|
2023-11-08 09:55:42 +00:00
|
|
|
/*
|
2024-01-23 23:23:31 +00:00
|
|
|
* snmp_register_ack - handle registration response
|
2023-11-08 09:55:42 +00:00
|
|
|
* @p: SNMP protocol instance
|
|
|
|
* @res: header of agentx-Response-PDU
|
2024-07-23 11:48:20 +00:00
|
|
|
* @mib: MIB subtree identifier
|
2023-11-08 09:55:42 +00:00
|
|
|
*/
|
2023-10-25 14:44:08 +00:00
|
|
|
void
|
2024-07-23 11:48:20 +00:00
|
|
|
snmp_register_ack(struct snmp_proto *p, struct agentx_response *res, const struct oid *oid)
|
2023-10-25 14:44:08 +00:00
|
|
|
{
|
2024-07-23 11:48:20 +00:00
|
|
|
enum agentx_mibs mib = agentx_get_mib(oid);
|
|
|
|
|
2023-11-15 14:03:55 +00:00
|
|
|
struct snmp_registration *reg;
|
|
|
|
WALK_LIST(reg, p->registration_queue)
|
2023-10-25 14:44:08 +00:00
|
|
|
{
|
2024-07-23 11:48:20 +00:00
|
|
|
if (snmp_registration_match(reg, &res->h, mib))
|
2023-10-25 14:44:08 +00:00
|
|
|
{
|
|
|
|
rem_node(®->n);
|
2023-11-15 14:03:55 +00:00
|
|
|
p->registrations_to_ack--;
|
2023-10-25 14:44:08 +00:00
|
|
|
|
2023-10-25 14:57:46 +00:00
|
|
|
if (res->error == AGENTX_RES_NO_ERROR)
|
2024-05-24 13:20:30 +00:00
|
|
|
reg->reg_hook_ok(p, (const struct agentx_response *) res, reg);
|
2023-10-25 14:57:46 +00:00
|
|
|
else
|
2024-05-24 13:20:30 +00:00
|
|
|
reg->reg_hook_fail(p, (const struct agentx_response *) res, reg);
|
|
|
|
|
|
|
|
mb_free(reg->oid);
|
|
|
|
mb_free(reg);
|
2023-10-25 14:44:08 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-11-08 09:55:42 +00:00
|
|
|
/*
|
|
|
|
* snmp_simple_response - send an agentx-Response-PDU with no data payload
|
|
|
|
* @p: SNMP protocol instance
|
2024-01-23 23:23:31 +00:00
|
|
|
* @error: response PDU error fields value
|
|
|
|
* @index: response PDU error index field value
|
2024-01-10 11:21:46 +00:00
|
|
|
*
|
|
|
|
* This function assumes that the buffer has enough space to fill in the AgentX
|
|
|
|
* Response PDU. So it is the responsibility of the caller to provide that.
|
2023-11-08 09:55:42 +00:00
|
|
|
*/
|
2023-10-25 10:41:23 +00:00
|
|
|
static void
|
2023-11-08 09:55:42 +00:00
|
|
|
snmp_simple_response(struct snmp_proto *p, enum agentx_response_errs error, u16 index)
|
2023-10-25 10:41:23 +00:00
|
|
|
{
|
|
|
|
sock *sk = p->sock;
|
2023-11-15 10:29:19 +00:00
|
|
|
struct snmp_pdu c;
|
2024-07-17 11:03:26 +00:00
|
|
|
snmp_pdu_context(&c, p, sk);
|
2023-10-25 10:41:23 +00:00
|
|
|
|
2024-01-10 11:21:46 +00:00
|
|
|
ASSUME(c.size >= sizeof(struct agentx_response));
|
2023-10-25 10:41:23 +00:00
|
|
|
|
|
|
|
struct agentx_response *res = prepare_response(p, &c);
|
2024-01-10 11:21:46 +00:00
|
|
|
response_err_ind(p, res, error, index);
|
2023-10-25 10:41:23 +00:00
|
|
|
sk_send(sk, sizeof(struct agentx_response));
|
|
|
|
}
|
|
|
|
|
2023-11-08 09:55:42 +00:00
|
|
|
/*
|
|
|
|
* open_pdu - send an agentx-Open-PDU
|
|
|
|
* @p: SNMP protocol instance
|
|
|
|
* @oid: PDU OID description field value
|
|
|
|
*
|
2024-01-10 11:21:46 +00:00
|
|
|
* Other fields are filled based on @p configuration (timeout, subagent string
|
2023-11-08 09:55:42 +00:00
|
|
|
* description)
|
|
|
|
*/
|
2022-09-06 16:04:29 +00:00
|
|
|
static void
|
|
|
|
open_pdu(struct snmp_proto *p, struct oid *oid)
|
2022-08-10 15:31:32 +00:00
|
|
|
{
|
2023-09-04 11:58:59 +00:00
|
|
|
const struct snmp_config *cf = SKIP_BACK(struct snmp_config, cf, p->p.cf);
|
2022-09-06 16:04:29 +00:00
|
|
|
sock *sk = p->sock;
|
2023-09-04 07:25:51 +00:00
|
|
|
|
2023-11-15 10:29:19 +00:00
|
|
|
struct snmp_pdu c;
|
2024-07-17 11:03:26 +00:00
|
|
|
snmp_pdu_context(&c, p, sk);
|
2022-09-06 16:04:29 +00:00
|
|
|
|
2024-01-23 23:23:31 +00:00
|
|
|
#define TIMEOUT_SIZE sizeof(u32) /* 1B timeout, 3B zero padding */
|
|
|
|
|
|
|
|
/* Make sure that we have enough space in TX-buffer */
|
2024-07-23 11:48:20 +00:00
|
|
|
uint s = AGENTX_HEADER_SIZE + TIMEOUT_SIZE + snmp_oid_size(oid) +
|
|
|
|
snmp_str_size(cf->description);
|
|
|
|
if (snmp_tbuf_reserve(&c, s))
|
2024-07-04 14:33:44 +00:00
|
|
|
snmp_log("agentx-Open-PDU small buffer");
|
2022-09-06 16:04:29 +00:00
|
|
|
|
2024-01-23 23:23:31 +00:00
|
|
|
struct agentx_header *h = (void *) c.buffer;
|
2023-08-08 17:00:54 +00:00
|
|
|
ADVANCE(c.buffer, c.size, AGENTX_HEADER_SIZE);
|
2023-11-15 11:37:10 +00:00
|
|
|
snmp_blank_header(h, AGENTX_OPEN_PDU);
|
2022-09-06 16:04:29 +00:00
|
|
|
|
2023-07-26 12:30:34 +00:00
|
|
|
STORE_U32(h->session_id, 1);
|
|
|
|
STORE_U32(h->transaction_id, 1);
|
|
|
|
STORE_U32(h->packet_id, 1);
|
2022-09-06 16:04:29 +00:00
|
|
|
|
2023-09-04 11:58:59 +00:00
|
|
|
c.size -= (4 + snmp_oid_size(oid) + snmp_str_size(cf->description));
|
2023-11-15 14:03:55 +00:00
|
|
|
|
2024-01-10 11:21:46 +00:00
|
|
|
if (p->timeout >= 1 S && p->timeout <= 255 S)
|
2023-11-15 14:03:55 +00:00
|
|
|
/* use p->timeout ceiled up to whole second */
|
|
|
|
c.buffer = snmp_put_fbyte(c.buffer,
|
|
|
|
(p->timeout % (1 S) == 0) ? p->timeout TO_S : p->timeout TO_S + 1);
|
|
|
|
/* out of range fallbacks */
|
|
|
|
else if (p->timeout < 1 TO_US)
|
|
|
|
c.buffer = snmp_put_fbyte(c.buffer, (u8) 1);
|
|
|
|
else /* p->timeout > 255 TO_US */
|
|
|
|
c.buffer = snmp_put_fbyte(c.buffer, (u8) 255);
|
|
|
|
|
2023-07-26 12:30:34 +00:00
|
|
|
c.buffer = snmp_put_oid(c.buffer, oid);
|
2023-09-04 11:58:59 +00:00
|
|
|
c.buffer = snmp_put_str(c.buffer, cf->description);
|
2022-09-06 16:04:29 +00:00
|
|
|
|
2024-07-23 11:48:20 +00:00
|
|
|
s = update_packet_size(h, c.buffer);
|
2023-10-19 14:20:37 +00:00
|
|
|
sk_send(sk, s);
|
2023-10-18 16:06:24 +00:00
|
|
|
#undef TIMEOUT_SIZE
|
2023-07-26 12:30:34 +00:00
|
|
|
}
|
|
|
|
|
2023-11-08 09:55:42 +00:00
|
|
|
/*
|
|
|
|
* 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
|
|
|
|
*/
|
2023-09-04 11:53:45 +00:00
|
|
|
void
|
2023-09-04 11:58:59 +00:00
|
|
|
snmp_notify_pdu(struct snmp_proto *p, struct oid *oid, void *data, uint size, int include_uptime)
|
2023-07-26 12:30:34 +00:00
|
|
|
{
|
|
|
|
sock *sk = p->sock;
|
|
|
|
|
2023-11-15 10:29:19 +00:00
|
|
|
struct snmp_pdu c;
|
2024-07-17 11:03:26 +00:00
|
|
|
snmp_pdu_context(&c, p, sk);
|
2023-07-26 12:30:34 +00:00
|
|
|
|
2024-07-23 11:48:20 +00:00
|
|
|
#define UPTIME_SIZE sizeof(STATIC_OID(4)) /* see sys_up_time_0 */
|
|
|
|
#define TRAP0_HEADER_SIZE sizeof(STATIC_OID(6)) /* see snmp_trap_oid_0 */
|
2023-07-26 12:30:34 +00:00
|
|
|
|
2023-09-04 07:25:51 +00:00
|
|
|
uint sz = AGENTX_HEADER_SIZE + TRAP0_HEADER_SIZE + snmp_oid_size(oid) \
|
2023-09-04 11:46:02 +00:00
|
|
|
+ size;
|
2023-09-04 07:25:51 +00:00
|
|
|
|
|
|
|
if (include_uptime)
|
|
|
|
sz += UPTIME_SIZE;
|
2023-09-04 11:46:02 +00:00
|
|
|
|
2024-01-23 23:23:31 +00:00
|
|
|
/* Make sure that we have enough space in TX-buffer */
|
2024-07-23 11:48:20 +00:00
|
|
|
if (snmp_tbuf_reserve(&c, sz))
|
2024-07-04 14:33:44 +00:00
|
|
|
snmp_log("agentx-Notify-PDU small buffer");
|
2023-09-04 07:25:51 +00:00
|
|
|
|
2024-07-24 11:38:36 +00:00
|
|
|
struct agentx_header *h = (struct agentx_header *) c.buffer;
|
2023-09-04 11:46:02 +00:00
|
|
|
ADVANCE(c.buffer, c.size, AGENTX_HEADER_SIZE);
|
2023-11-15 11:37:10 +00:00
|
|
|
snmp_blank_header(h, AGENTX_NOTIFY_PDU);
|
2024-01-23 23:23:31 +00:00
|
|
|
p->packet_id++; /* New packet id */
|
2023-11-15 11:37:10 +00:00
|
|
|
snmp_session(p, h);
|
2023-09-04 11:46:02 +00:00
|
|
|
|
2023-09-04 07:25:51 +00:00
|
|
|
if (include_uptime)
|
2023-07-26 12:30:34 +00:00
|
|
|
{
|
2023-09-04 07:25:51 +00:00
|
|
|
/* sysUpTime.0 oid */
|
2024-07-22 16:17:16 +00:00
|
|
|
STATIC_OID(4) sys_up_time_0 = {
|
2023-09-04 07:25:51 +00:00
|
|
|
.n_subid = 4,
|
2023-09-04 11:51:29 +00:00
|
|
|
.prefix = SNMP_MGMT,
|
2023-09-04 07:25:51 +00:00
|
|
|
.include = 0,
|
2024-01-23 23:23:31 +00:00
|
|
|
.reserved = 0,
|
2024-07-22 16:17:16 +00:00
|
|
|
.ids = { SNMP_MIB_2, SNMP_SYSTEM, SNMP_SYS_UP_TIME, 0 },
|
2023-09-04 07:25:51 +00:00
|
|
|
};
|
2024-07-22 16:17:16 +00:00
|
|
|
struct oid *uptime_0 = (struct oid *) &sys_up_time_0;
|
2023-09-04 07:25:51 +00:00
|
|
|
|
2024-07-22 16:17:16 +00:00
|
|
|
struct agentx_varbind *vb = snmp_create_varbind(c.buffer, uptime_0);
|
|
|
|
for (uint i = 0; i < uptime_0->n_subid; i++)
|
|
|
|
STORE_U32(vb->name.ids[i], uptime_0->ids[i]);
|
2024-01-10 11:21:46 +00:00
|
|
|
|
2024-01-23 23:23:31 +00:00
|
|
|
/* TODO use time from last reconfiguration instead? [config->load_time] */
|
2024-01-10 11:21:46 +00:00
|
|
|
btime uptime = current_time() - boot_time;
|
2024-05-24 13:20:30 +00:00
|
|
|
snmp_varbind_ticks(&c, (uptime TO_S) / 100);
|
2024-01-10 11:21:46 +00:00
|
|
|
ASSUME(snmp_test_varbind(vb));
|
|
|
|
ADVANCE(c.buffer, c.size, snmp_varbind_size_unsafe(vb));
|
2023-07-26 12:30:34 +00:00
|
|
|
}
|
|
|
|
|
2023-09-04 07:25:51 +00:00
|
|
|
/* snmpTrapOID.0 oid */
|
2024-07-22 16:17:16 +00:00
|
|
|
STATIC_OID(6) snmp_trap_oid_0 = {
|
2023-09-04 07:25:51 +00:00
|
|
|
.n_subid = 6,
|
2024-07-22 16:17:16 +00:00
|
|
|
.prefix = SNMP_V2,
|
2023-09-04 07:25:51 +00:00
|
|
|
.include = 0,
|
2024-01-23 23:23:31 +00:00
|
|
|
.reserved = 0,
|
2024-07-22 16:17:16 +00:00
|
|
|
.ids = { SNMP_MODULES, SNMP_ALARM_NEXT_INDEX, SNMP_MIB_OBJECTS, SNMP_TRAP, SNMP_TRAP_OID, 0 },
|
2023-09-04 07:25:51 +00:00
|
|
|
};
|
2024-07-22 16:17:16 +00:00
|
|
|
struct oid *trap_0 = (struct oid *) &snmp_trap_oid_0;
|
2023-09-04 11:58:59 +00:00
|
|
|
|
2024-07-22 16:17:16 +00:00
|
|
|
struct agentx_varbind *trap_vb = snmp_create_varbind(c.buffer, trap_0);
|
|
|
|
for (uint i = 0; i < trap_0->n_subid; i++)
|
|
|
|
STORE_U32(trap_vb->name.ids[i], trap_0->ids[i]);
|
2023-09-04 07:25:51 +00:00
|
|
|
trap_vb->type = AGENTX_OBJECT_ID;
|
2023-11-15 10:29:19 +00:00
|
|
|
snmp_put_oid(snmp_varbind_data(trap_vb), oid);
|
2024-01-10 11:21:46 +00:00
|
|
|
ADVANCE(c.buffer, c.size, snmp_varbind_size_unsafe(trap_vb));
|
2023-07-26 12:30:34 +00:00
|
|
|
|
2023-09-04 11:58:59 +00:00
|
|
|
memcpy(c.buffer, data, size);
|
|
|
|
ADVANCE(c.buffer, c.size, size);
|
2023-09-04 07:25:51 +00:00
|
|
|
|
2024-01-23 23:23:31 +00:00
|
|
|
uint s = update_packet_size(h, c.buffer);
|
2023-10-19 14:20:37 +00:00
|
|
|
sk_send(sk, s);
|
2022-08-10 15:31:32 +00:00
|
|
|
|
2023-09-04 07:25:51 +00:00
|
|
|
#undef TRAP0_HEADER_SIZE
|
2023-09-04 11:58:59 +00:00
|
|
|
#undef UPTIME_SIZE
|
2023-07-26 12:30:34 +00:00
|
|
|
}
|
|
|
|
|
2023-11-08 09:55:42 +00:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
2023-09-04 07:25:51 +00:00
|
|
|
static void
|
2024-01-23 23:23:31 +00:00
|
|
|
un_register_pdu(struct snmp_proto *p, struct oid *oid, u32 bound, uint index, enum agentx_pdu_types type, u8 is_instance, uint UNUSED contid)
|
2022-09-06 16:04:29 +00:00
|
|
|
{
|
2023-11-15 10:29:19 +00:00
|
|
|
/* used for agentx-Register-PDU and agentx-Unregister-PDU */
|
2023-09-04 12:01:08 +00:00
|
|
|
const struct snmp_config *cf = SKIP_BACK(struct snmp_config, cf, p->p.cf);
|
2022-09-06 16:04:29 +00:00
|
|
|
sock *sk = p->sock;
|
2023-11-15 10:29:19 +00:00
|
|
|
struct snmp_pdu c;
|
2024-07-17 11:03:26 +00:00
|
|
|
snmp_pdu_context(&c, p, sk);
|
2022-09-06 16:04:29 +00:00
|
|
|
|
2024-01-23 23:23:31 +00:00
|
|
|
#define BOUND_SIZE sizeof(u32)
|
2023-09-04 07:25:51 +00:00
|
|
|
/* conditional +4 for upper-bound (optinal field) */
|
2024-05-24 13:20:30 +00:00
|
|
|
uint sz = AGENTX_HEADER_SIZE + snmp_oid_size(oid) +
|
2024-01-23 23:23:31 +00:00
|
|
|
((bound > 1) ? BOUND_SIZE : 0);
|
2023-09-11 11:06:20 +00:00
|
|
|
|
2024-07-23 11:48:20 +00:00
|
|
|
if (snmp_tbuf_reserve(&c, sz))
|
2024-07-04 14:33:44 +00:00
|
|
|
snmp_log("agentx-Register-PDU small buffer");
|
2022-09-06 16:04:29 +00:00
|
|
|
|
2024-01-23 23:23:31 +00:00
|
|
|
struct agentx_header *h = (void *) c.buffer;
|
2023-09-11 11:06:20 +00:00
|
|
|
ADVANCE(c.buffer, c.size, AGENTX_HEADER_SIZE);
|
2023-07-26 12:30:34 +00:00
|
|
|
|
2023-11-15 11:37:10 +00:00
|
|
|
snmp_header(h, type, is_instance ? AGENTX_FLAG_INSTANCE_REGISTRATION : 0);
|
2023-08-08 17:00:54 +00:00
|
|
|
p->packet_id++;
|
2023-11-15 11:37:10 +00:00
|
|
|
snmp_session(p, h);
|
2023-07-26 12:30:34 +00:00
|
|
|
|
2023-09-11 11:06:20 +00:00
|
|
|
struct agentx_un_register_hdr *ur = (struct agentx_un_register_hdr *) c.buffer;
|
|
|
|
|
2023-11-15 14:03:55 +00:00
|
|
|
/* 0 = do not override session message timeout */
|
|
|
|
STORE_U8(ur->timeout, 0);
|
|
|
|
/* use selected priority */
|
2023-09-04 12:01:08 +00:00
|
|
|
STORE_U8(ur->priority, cf->priority);
|
2023-11-08 09:55:42 +00:00
|
|
|
STORE_U8(ur->range_subid, (bound > 1) ? index : 0);
|
2024-01-23 23:23:31 +00:00
|
|
|
STORE_U8(ur->reserved, 0);
|
2023-09-11 11:06:20 +00:00
|
|
|
ADVANCE(c.buffer, c.size, sizeof(struct agentx_un_register_hdr));
|
2023-07-26 12:30:34 +00:00
|
|
|
|
2024-07-24 11:38:36 +00:00
|
|
|
(void) snmp_put_oid(c.buffer, oid);
|
2023-07-26 12:30:34 +00:00
|
|
|
ADVANCE(c.buffer, c.size, snmp_oid_size(oid));
|
|
|
|
|
2023-09-04 07:25:51 +00:00
|
|
|
/* place upper-bound if needed */
|
2023-11-08 09:55:42 +00:00
|
|
|
if (bound > 1)
|
2023-07-26 12:30:34 +00:00
|
|
|
{
|
2023-11-08 09:55:42 +00:00
|
|
|
STORE_PTR(c.buffer, bound);
|
2024-01-23 23:23:31 +00:00
|
|
|
ADVANCE(c.buffer, c.size, BOUND_SIZE);
|
2023-07-26 12:30:34 +00:00
|
|
|
}
|
2022-09-06 16:04:29 +00:00
|
|
|
|
2024-01-23 23:23:31 +00:00
|
|
|
uint s = update_packet_size(h, c.buffer);
|
2022-08-10 15:31:32 +00:00
|
|
|
|
2023-10-19 14:20:37 +00:00
|
|
|
sk_send(sk, s);
|
2024-01-23 23:23:31 +00:00
|
|
|
#undef BOUND_SIZE
|
2022-09-06 16:04:29 +00:00
|
|
|
}
|
|
|
|
|
2023-11-08 09:55:42 +00:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
2022-12-10 17:08:00 +00:00
|
|
|
void
|
2024-01-23 23:23:31 +00:00
|
|
|
snmp_register(struct snmp_proto *p, struct oid *oid, u32 bound, uint index, u8 is_instance, uint contid)
|
2022-09-06 16:04:29 +00:00
|
|
|
{
|
2023-11-08 09:55:42 +00:00
|
|
|
un_register_pdu(p, oid, bound, index, AGENTX_REGISTER_PDU, is_instance, contid);
|
2022-09-06 16:04:29 +00:00
|
|
|
}
|
|
|
|
|
2023-11-08 09:55:42 +00:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
2024-07-22 16:17:16 +00:00
|
|
|
void
|
2024-01-23 23:23:31 +00:00
|
|
|
snmp_unregister(struct snmp_proto *p, struct oid *oid, u32 bound, uint index, uint contid)
|
2022-09-06 16:04:29 +00:00
|
|
|
{
|
2024-01-23 23:23:31 +00:00
|
|
|
un_register_pdu(p, oid, bound, index, AGENTX_UNREGISTER_PDU, 0, contid);
|
2022-08-10 15:31:32 +00:00
|
|
|
}
|
|
|
|
|
2023-11-08 09:55:42 +00:00
|
|
|
/*
|
|
|
|
* close_pdu - send an agentx-Close-PDU
|
|
|
|
* @p: SNMP protocol instance
|
|
|
|
* @reason: reason for closure
|
|
|
|
*/
|
2024-07-22 16:17:16 +00:00
|
|
|
static void
|
2023-11-08 09:55:42 +00:00
|
|
|
close_pdu(struct snmp_proto *p, enum agentx_close_reasons reason)
|
2022-08-02 14:04:25 +00:00
|
|
|
{
|
2022-08-10 15:31:32 +00:00
|
|
|
sock *sk = p->sock;
|
2023-11-15 10:29:19 +00:00
|
|
|
struct snmp_pdu c;
|
2024-07-17 11:03:26 +00:00
|
|
|
snmp_pdu_context(&c, p, sk);
|
2023-07-26 12:30:34 +00:00
|
|
|
|
2024-01-23 23:23:31 +00:00
|
|
|
#define REASON_SIZE sizeof(u32)
|
2024-07-23 11:48:20 +00:00
|
|
|
if (snmp_tbuf_reserve(&c, AGENTX_HEADER_SIZE + REASON_SIZE))
|
2024-07-04 14:33:44 +00:00
|
|
|
snmp_log("agentx-Close-PDU small buffer");
|
2023-07-26 12:30:34 +00:00
|
|
|
|
2024-01-23 23:23:31 +00:00
|
|
|
struct agentx_header *h = (void *) c.buffer;
|
2023-07-26 12:30:34 +00:00
|
|
|
ADVANCE(c.buffer, c.size, AGENTX_HEADER_SIZE);
|
2023-11-15 11:37:10 +00:00
|
|
|
snmp_blank_header(h, AGENTX_CLOSE_PDU);
|
2023-08-08 17:00:54 +00:00
|
|
|
p->packet_id++;
|
2023-11-15 11:37:10 +00:00
|
|
|
snmp_session(p, h);
|
2023-07-26 12:30:34 +00:00
|
|
|
|
2023-11-08 09:55:42 +00:00
|
|
|
snmp_put_fbyte(c.buffer, (u8) reason);
|
2023-07-26 12:30:34 +00:00
|
|
|
ADVANCE(c.buffer, c.size, 4);
|
|
|
|
|
2024-01-23 23:23:31 +00:00
|
|
|
uint s = update_packet_size(h, c.buffer);
|
2023-10-19 14:20:37 +00:00
|
|
|
sk_send(sk, s);
|
2023-10-25 10:41:23 +00:00
|
|
|
#undef REASON_SIZE
|
2023-07-26 12:30:34 +00:00
|
|
|
}
|
|
|
|
|
2023-11-08 09:55:42 +00:00
|
|
|
/*
|
|
|
|
* parse_close_pdu - parse an agentx-Close-PDU
|
|
|
|
* @p: SNMP protocol instance
|
|
|
|
* @pkt_start: pointer to first byte of PDU
|
|
|
|
*
|
|
|
|
* Return number of bytes parsed from RX-buffer.
|
|
|
|
*/
|
2023-10-25 10:56:23 +00:00
|
|
|
static uint
|
2024-01-23 23:23:31 +00:00
|
|
|
parse_close_pdu(struct snmp_proto *p, byte * const pkt_start)
|
2023-10-19 14:27:04 +00:00
|
|
|
{
|
2023-11-15 14:03:55 +00:00
|
|
|
TRACE(D_PACKETS, "SNMP received agentx-Close-PDU");
|
2023-10-25 10:56:23 +00:00
|
|
|
byte *pkt = pkt_start;
|
2023-10-19 14:27:04 +00:00
|
|
|
|
2024-01-23 23:23:31 +00:00
|
|
|
struct agentx_close_pdu *pdu = (void *) pkt;
|
|
|
|
pkt += sizeof(struct agentx_close_pdu);
|
|
|
|
uint pkt_size = pdu->h.payload;
|
|
|
|
|
|
|
|
if (pkt_size != sizeof(struct agentx_close_pdu))
|
2023-10-19 14:27:04 +00:00
|
|
|
{
|
2024-01-10 11:21:46 +00:00
|
|
|
TRACE(D_PACKETS, "SNMP malformed agentx-Close-PDU, closing anyway");
|
2023-10-25 10:56:23 +00:00
|
|
|
snmp_simple_response(p, AGENTX_RES_GEN_ERROR, 0);
|
2024-01-10 11:21:46 +00:00
|
|
|
snmp_set_state(p, SNMP_RESET);
|
2024-01-23 23:23:31 +00:00
|
|
|
return MIN(pkt_size + AGENTX_HEADER_SIZE, sizeof(struct agentx_close_pdu));
|
2023-11-15 14:03:55 +00:00
|
|
|
}
|
2024-01-10 11:21:46 +00:00
|
|
|
|
|
|
|
if (!snmp_test_close_reason(pdu->reason))
|
2023-11-15 14:03:55 +00:00
|
|
|
{
|
2024-01-23 23:23:31 +00:00
|
|
|
TRACE(D_PACKETS, "SNMP invalid close reason %u", pdu->reason);
|
2024-01-10 11:21:46 +00:00
|
|
|
snmp_simple_response(p, AGENTX_RES_GEN_ERROR, 0);
|
|
|
|
snmp_set_state(p, SNMP_RESET);
|
2024-01-23 23:23:31 +00:00
|
|
|
return pkt_size + AGENTX_HEADER_SIZE;
|
2023-10-19 14:27:04 +00:00
|
|
|
}
|
|
|
|
|
2024-01-10 11:21:46 +00:00
|
|
|
enum agentx_close_reasons reason = (enum agentx_close_reasons) pdu->reason;
|
|
|
|
TRACE(D_PACKETS, "SNMP close reason %u", reason);
|
|
|
|
snmp_simple_response(p, AGENTX_RES_NO_ERROR, 0);
|
2023-11-15 14:03:55 +00:00
|
|
|
snmp_set_state(p, SNMP_RESET);
|
2024-01-23 23:23:31 +00:00
|
|
|
return pkt_size + AGENTX_HEADER_SIZE;
|
2023-07-26 12:30:34 +00:00
|
|
|
}
|
|
|
|
|
2023-11-08 09:55:42 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* refresh_ids - Copy current ids from packet to protocol
|
|
|
|
* @p: SNMP protocol instance
|
|
|
|
* @h: PDU header with new transaction_id and packet_id ids.
|
|
|
|
*/
|
2022-09-06 16:04:29 +00:00
|
|
|
static inline void
|
|
|
|
refresh_ids(struct snmp_proto *p, struct agentx_header *h)
|
|
|
|
{
|
2023-11-15 11:37:10 +00:00
|
|
|
p->transaction_id = LOAD_U32(h->transaction_id);
|
|
|
|
p->packet_id = LOAD_U32(h->packet_id);
|
2022-09-06 16:04:29 +00:00
|
|
|
}
|
|
|
|
|
2023-11-08 09:55:42 +00:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
2024-01-23 23:23:31 +00:00
|
|
|
static inline uint
|
|
|
|
parse_test_set_pdu(struct snmp_proto *p, byte * const pkt_start)
|
2023-10-19 14:27:04 +00:00
|
|
|
{
|
2023-11-15 10:29:19 +00:00
|
|
|
TRACE(D_PACKETS, "SNMP received agentx-TestSet-PDU");
|
2023-10-25 10:41:23 +00:00
|
|
|
byte *pkt = pkt_start; /* pointer to agentx-TestSet-PDU in RX-buffer */
|
2023-10-19 14:27:04 +00:00
|
|
|
uint s; /* final packat size */
|
|
|
|
struct agentx_response *res; /* pointer to reponse in TX-buffer */
|
|
|
|
|
|
|
|
struct agentx_header *h = (void *) pkt;
|
2024-01-23 23:23:31 +00:00
|
|
|
pkt += AGENTX_HEADER_SIZE;
|
2023-10-25 14:57:46 +00:00
|
|
|
|
2023-10-19 14:27:04 +00:00
|
|
|
sock *sk = p->sock;
|
2023-11-15 10:29:19 +00:00
|
|
|
struct snmp_pdu c;
|
2024-07-17 11:03:26 +00:00
|
|
|
snmp_pdu_context(&c, p, sk);
|
2023-10-19 14:27:04 +00:00
|
|
|
|
2024-07-23 11:48:20 +00:00
|
|
|
if (snmp_tbuf_reserve(&c, AGENTX_HEADER_SIZE))
|
2024-07-04 14:33:44 +00:00
|
|
|
snmp_log("agentx-TestSet-PDU small buffer");
|
2023-10-19 14:27:04 +00:00
|
|
|
|
|
|
|
res = prepare_response(p, &c);
|
|
|
|
|
|
|
|
/* 0 if there is piece, that we cannot set */
|
|
|
|
int all_possible = 0;
|
|
|
|
/* the all_possible is currently hard-coded with no support for writing to mib
|
|
|
|
* variables, when implementing the mentioned support, change the initializer
|
|
|
|
* to 1
|
|
|
|
*/
|
2024-01-23 23:23:31 +00:00
|
|
|
s = update_packet_size(h, c.buffer);
|
2023-10-19 14:27:04 +00:00
|
|
|
|
|
|
|
if (c.error != AGENTX_RES_NO_ERROR)
|
2023-10-25 10:56:23 +00:00
|
|
|
{
|
2024-01-10 11:21:46 +00:00
|
|
|
response_err_ind(p, res, c.error, c.index + 1);
|
2024-07-24 11:38:36 +00:00
|
|
|
snmp_reset(p);
|
2023-10-25 10:56:23 +00:00
|
|
|
}
|
2023-10-19 14:27:04 +00:00
|
|
|
else if (all_possible)
|
2023-11-15 14:03:55 +00:00
|
|
|
{
|
2024-01-10 11:21:46 +00:00
|
|
|
response_err_ind(p, res, AGENTX_RES_NO_ERROR, 0);
|
2023-11-15 14:03:55 +00:00
|
|
|
}
|
2023-10-19 14:27:04 +00:00
|
|
|
else
|
2023-11-15 14:03:55 +00:00
|
|
|
{
|
|
|
|
TRACE(D_PACKETS, "SNMP SET action failed (not writable)");
|
2024-01-10 11:21:46 +00:00
|
|
|
/* This is a recoverable error, we do not need to reset the connection */
|
|
|
|
response_err_ind(p, res, AGENTX_RES_NOT_WRITABLE, c.index + 1);
|
2023-11-15 14:03:55 +00:00
|
|
|
}
|
2023-10-19 14:27:04 +00:00
|
|
|
|
|
|
|
sk_send(sk, s);
|
|
|
|
return pkt - pkt_start;
|
|
|
|
}
|
|
|
|
|
2023-10-25 10:41:23 +00:00
|
|
|
/*
|
2024-01-10 11:21:46 +00:00
|
|
|
* parse_sets_pdu - common functionality for commit set and undo set PDUs
|
2023-11-08 09:55:42 +00:00
|
|
|
* @p: SNMP protocol instance
|
|
|
|
* @pkt_start: pointer to first byte of on of set related PDU
|
|
|
|
* @error: error status to use
|
|
|
|
*
|
|
|
|
* Return number of bytes parsed from RX-buffer.
|
2023-10-25 10:41:23 +00:00
|
|
|
*/
|
2023-10-19 14:27:04 +00:00
|
|
|
static uint
|
2024-01-23 23:23:31 +00:00
|
|
|
parse_sets_pdu(struct snmp_proto *p, byte * const pkt_start, enum agentx_response_errs err)
|
2023-10-19 14:27:04 +00:00
|
|
|
{
|
2023-10-25 10:41:23 +00:00
|
|
|
byte *pkt = pkt_start;
|
2023-10-19 14:27:04 +00:00
|
|
|
struct agentx_header *h = (void *) pkt;
|
2024-01-23 23:23:31 +00:00
|
|
|
pkt += AGENTX_HEADER_SIZE;
|
2023-11-15 11:37:10 +00:00
|
|
|
uint pkt_size = LOAD_U32(h->payload);
|
2023-10-19 14:27:04 +00:00
|
|
|
|
2023-10-25 10:41:23 +00:00
|
|
|
if (pkt_size != 0)
|
|
|
|
{
|
2023-11-15 14:03:55 +00:00
|
|
|
TRACE(D_PACKETS, "SNMP received malformed set PDU (size)");
|
2023-10-25 10:41:23 +00:00
|
|
|
snmp_simple_response(p, AGENTX_RES_PARSE_ERROR, 0);
|
2024-01-23 23:23:31 +00:00
|
|
|
// TODO best solution for possibly malicious pkt_size
|
|
|
|
return AGENTX_HEADER_SIZE;
|
2023-10-25 10:41:23 +00:00
|
|
|
}
|
|
|
|
|
2023-11-15 10:29:19 +00:00
|
|
|
struct snmp_pdu c;
|
2024-07-17 11:03:26 +00:00
|
|
|
snmp_pdu_context(&c, p, p->sock);
|
2024-07-23 11:48:20 +00:00
|
|
|
if (snmp_tbuf_reserve(&c, sizeof(struct agentx_response)))
|
2024-07-04 14:33:44 +00:00
|
|
|
snmp_log("parse_sets_pdu small buffer");
|
2023-10-19 14:27:04 +00:00
|
|
|
|
|
|
|
struct agentx_response *r = prepare_response(p, &c);
|
|
|
|
|
2024-01-23 23:23:31 +00:00
|
|
|
// TODO free resource allocated by parse_test_set_pdu()
|
|
|
|
// TODO do something meaningful
|
|
|
|
//mb_free(tr);
|
|
|
|
c.error = err;
|
2023-10-19 14:27:04 +00:00
|
|
|
|
2023-11-15 14:03:55 +00:00
|
|
|
TRACE(D_PACKETS, "SNMP received set PDU with error %u", c.error);
|
2024-01-10 11:21:46 +00:00
|
|
|
response_err_ind(p, r, c.error, 0);
|
2023-10-19 14:27:04 +00:00
|
|
|
sk_send(p->sock, AGENTX_HEADER_SIZE);
|
2023-10-25 10:56:23 +00:00
|
|
|
|
|
|
|
/* Reset the connection on unrecoverable error */
|
|
|
|
if (c.error != AGENTX_RES_NO_ERROR && c.error != err)
|
2024-07-22 16:17:16 +00:00
|
|
|
snmp_reset(p); /* error */
|
2023-10-25 10:56:23 +00:00
|
|
|
|
2023-10-19 14:27:04 +00:00
|
|
|
return pkt - pkt_start;
|
|
|
|
}
|
|
|
|
|
2023-11-08 09:55:42 +00:00
|
|
|
/*
|
|
|
|
* parse_commit_set_pdu - parse an agentx-CommitSet-PDU
|
|
|
|
* @p: SNMP protocol instance
|
|
|
|
* @pkt: pointer to first byte of PDU inside RX-buffer
|
|
|
|
*
|
|
|
|
* Return number of bytes parsed from RX-buffer.
|
|
|
|
*/
|
2024-01-23 23:23:31 +00:00
|
|
|
static inline uint
|
|
|
|
parse_commit_set_pdu(struct snmp_proto *p, byte *pkt)
|
2023-10-19 14:27:04 +00:00
|
|
|
{
|
|
|
|
// don't forget to free resoures allocated by parse_test_set_pdu()
|
|
|
|
//mb_free(tr);
|
2023-11-15 14:03:55 +00:00
|
|
|
TRACE(D_PACKETS, "SNMP received agentx-CommitSet-PDU");
|
2024-01-23 23:23:31 +00:00
|
|
|
return parse_sets_pdu(p, pkt, AGENTX_RES_COMMIT_FAILED);
|
2023-10-19 14:27:04 +00:00
|
|
|
}
|
|
|
|
|
2023-11-08 09:55:42 +00:00
|
|
|
/*
|
|
|
|
* parse_undo_set_pdu - parse an agentx-UndoSet-PDU
|
|
|
|
* @p: SNMP protocol instance
|
|
|
|
* @pkt: pointer to first byte of PDU inside RX-buffer
|
|
|
|
*
|
|
|
|
* Return number of bytes parsed from buffer.
|
|
|
|
*/
|
2024-01-23 23:23:31 +00:00
|
|
|
static inline uint
|
|
|
|
parse_undo_set_pdu(struct snmp_proto *p, byte *pkt)
|
2023-10-19 14:27:04 +00:00
|
|
|
{
|
|
|
|
// don't forget to free resources allocated by parse_test_set_pdu()
|
|
|
|
//mb_free(tr);
|
2023-11-15 14:03:55 +00:00
|
|
|
TRACE(D_PACKETS, "SNMP received agentx-UndoSet-PDU");
|
2024-01-23 23:23:31 +00:00
|
|
|
return parse_sets_pdu(p, pkt, AGENTX_RES_UNDO_FAILED);
|
2023-10-19 14:27:04 +00:00
|
|
|
}
|
|
|
|
|
2023-11-08 09:55:42 +00:00
|
|
|
/*
|
|
|
|
* parse_cleanup_set_pdu - parse an agentx-CleanupSet-PDU
|
|
|
|
* @p: SNMP protocol instance
|
|
|
|
* @pkt_start: pointer to first byte of PDU inside RX-buffer
|
|
|
|
*
|
|
|
|
* Return number of bytes parsed from RX-buffer.
|
|
|
|
*/
|
2023-10-19 14:27:04 +00:00
|
|
|
static uint
|
2024-01-23 23:23:31 +00:00
|
|
|
parse_cleanup_set_pdu(struct snmp_proto *p, byte * const pkt_start)
|
2023-10-19 14:27:04 +00:00
|
|
|
{
|
2023-11-15 14:03:55 +00:00
|
|
|
TRACE(D_PACKETS, "SNMP received agentx-CleanupSet-PDU");
|
2023-10-25 10:41:23 +00:00
|
|
|
(void)p;
|
2024-01-23 23:23:31 +00:00
|
|
|
// TODO don't forget to free resources allocated by parse_test_set_pdu()
|
2023-10-25 10:41:23 +00:00
|
|
|
//mb_free(p->tr);
|
2023-10-19 14:27:04 +00:00
|
|
|
|
2023-10-25 10:41:23 +00:00
|
|
|
byte *pkt = pkt_start;
|
2023-10-19 14:27:04 +00:00
|
|
|
struct agentx_header *h = (void *) pkt;
|
2023-11-15 11:37:10 +00:00
|
|
|
uint pkt_size = LOAD_U32(h->payload);
|
2023-10-25 10:41:23 +00:00
|
|
|
|
|
|
|
/* errors are dropped silently, we must not send any agentx-Response-PDU */
|
|
|
|
if (pkt_size != 0)
|
|
|
|
{
|
|
|
|
// TODO should we free even for malformed packets ??
|
2024-05-24 13:20:30 +00:00
|
|
|
// TODO -> check that data is not freed
|
2024-01-23 23:23:31 +00:00
|
|
|
return AGENTX_HEADER_SIZE;
|
2023-10-25 10:41:23 +00:00
|
|
|
}
|
2023-10-19 14:27:04 +00:00
|
|
|
|
|
|
|
/* No agentx-Response-PDU is sent in response to agentx-CleanupSet-PDU */
|
2023-10-25 10:41:23 +00:00
|
|
|
return pkt_size;
|
2023-10-19 14:27:04 +00:00
|
|
|
}
|
|
|
|
|
2024-01-10 11:21:46 +00:00
|
|
|
/*
|
|
|
|
* space_for_response - check if TX-buffer has space for agentx-Response-PDU
|
|
|
|
* @sk: communication socket owned by SNMP protocol instance
|
|
|
|
*
|
|
|
|
* In some cases we send only the AgentX header but if we want to signal an
|
|
|
|
* error, we need at least space for agentx-Response-PDU. This simplifies the
|
|
|
|
* PDU space requirements testing.
|
|
|
|
*/
|
|
|
|
static inline int
|
|
|
|
space_for_response(const sock *sk)
|
|
|
|
{
|
|
|
|
return (
|
|
|
|
(uint) (sk->tbuf + sk->tbsize - sk->tpos) >= sizeof(struct agentx_response)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2023-03-14 13:10:08 +00:00
|
|
|
/**
|
2023-11-08 09:55:42 +00:00
|
|
|
* 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
|
2023-03-14 13:10:08 +00:00
|
|
|
*
|
2023-11-08 09:55:42 +00:00
|
|
|
* Return number of bytes parsed from RX-buffer.
|
2023-03-14 13:10:08 +00:00
|
|
|
*/
|
|
|
|
static uint
|
2024-01-23 23:23:31 +00:00
|
|
|
parse_pkt(struct snmp_proto *p, byte *pkt, uint size)
|
2022-08-10 15:31:32 +00:00
|
|
|
{
|
2023-07-26 12:30:34 +00:00
|
|
|
if (size < AGENTX_HEADER_SIZE)
|
2022-08-10 15:31:32 +00:00
|
|
|
return 0;
|
|
|
|
|
2024-07-24 11:38:36 +00:00
|
|
|
struct agentx_header *h = (struct agentx_header *) pkt;
|
2024-07-04 14:33:44 +00:00
|
|
|
if (h->flags & AGENTX_NETWORK_BYTE_ORDER)
|
|
|
|
{
|
|
|
|
TRACE(D_PACKETS, "SNMP received PDU with unexpected byte order");
|
2024-07-24 11:38:36 +00:00
|
|
|
snmp_simple_response(p, AGENTX_RES_GEN_ERROR, 0);
|
2024-07-04 14:33:44 +00:00
|
|
|
snmp_reset(p);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2024-07-24 11:38:36 +00:00
|
|
|
u32 pkt_size = LOAD_U32(h->payload);
|
2022-12-10 17:08:00 +00:00
|
|
|
|
2024-01-23 23:23:31 +00:00
|
|
|
/* RX side checks - too big packet */
|
2024-01-10 11:21:46 +00:00
|
|
|
if (pkt_size > SNMP_PKT_SIZE_MAX)
|
2024-01-23 23:23:31 +00:00
|
|
|
{
|
2024-07-24 11:38:36 +00:00
|
|
|
TRACE(D_PACKETS, "SNMP received PDU is too long");
|
2024-01-23 23:23:31 +00:00
|
|
|
snmp_simple_response(p, AGENTX_RES_GEN_ERROR, 0);
|
|
|
|
snmp_reset(p);
|
2024-07-04 14:33:44 +00:00
|
|
|
return 0; /* no bytes parsed */
|
2024-01-23 23:23:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* This guarantees that we have the full packet already received */
|
|
|
|
if (size < pkt_size + AGENTX_HEADER_SIZE)
|
|
|
|
return 0; /* no bytes parsed */
|
2024-01-10 11:21:46 +00:00
|
|
|
|
2024-07-24 11:38:36 +00:00
|
|
|
/*
|
|
|
|
* We need to see the responses for PDU such as
|
2023-10-25 10:41:23 +00:00
|
|
|
* agentx-Open-PDU, agentx-Register-PDU, ...
|
|
|
|
* even when we are outside the SNMP_CONNECTED state
|
|
|
|
*/
|
|
|
|
if (h->type == AGENTX_RESPONSE_PDU)
|
2024-01-23 23:23:31 +00:00
|
|
|
return parse_response(p, pkt);
|
2023-10-25 10:41:23 +00:00
|
|
|
|
2024-01-10 11:21:46 +00:00
|
|
|
ASSERT(snmp_is_active(p));
|
2023-10-25 10:41:23 +00:00
|
|
|
if (p->state != SNMP_CONN ||
|
2023-11-15 11:37:10 +00:00
|
|
|
p->session_id != LOAD_U32(h->session_id))
|
2022-08-10 15:31:32 +00:00
|
|
|
{
|
2023-10-25 10:41:23 +00:00
|
|
|
struct agentx_header copy = {
|
|
|
|
.session_id = p->session_id,
|
|
|
|
.transaction_id = p->transaction_id,
|
|
|
|
.packet_id = p->packet_id,
|
|
|
|
};
|
|
|
|
|
2023-11-15 14:03:55 +00:00
|
|
|
TRACE(D_PACKETS, "SNMP received PDU with unknown session id");
|
2023-10-25 10:41:23 +00:00
|
|
|
snmp_simple_response(p, AGENTX_RES_NOT_OPEN, 0);
|
|
|
|
|
|
|
|
p->session_id = copy.session_id;
|
|
|
|
p->transaction_id = copy.transaction_id;
|
|
|
|
p->packet_id = copy.packet_id;
|
|
|
|
|
2024-01-10 11:21:46 +00:00
|
|
|
/*
|
|
|
|
* After unexpected state, we simply reset the session
|
|
|
|
* only sending the agentx-Response-PDU.
|
|
|
|
*/
|
2024-01-23 23:23:31 +00:00
|
|
|
snmp_reset(p);
|
2024-07-04 14:33:44 +00:00
|
|
|
return 0;
|
2023-10-25 10:41:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (h->flags & AGENTX_NON_DEFAULT_CONTEXT)
|
|
|
|
{
|
2024-07-04 14:33:44 +00:00
|
|
|
TRACE(D_PACKETS, "SNMP received PDU with non-default context");
|
2023-10-25 10:41:23 +00:00
|
|
|
snmp_simple_response(p, AGENTX_RES_UNSUPPORTED_CONTEXT, 0);
|
2024-07-24 11:38:36 +00:00
|
|
|
snmp_reset(p);
|
|
|
|
return 0;
|
2023-10-25 10:41:23 +00:00
|
|
|
}
|
2022-09-06 16:04:29 +00:00
|
|
|
|
2023-10-25 10:41:23 +00:00
|
|
|
refresh_ids(p, h);
|
2024-07-24 11:38:36 +00:00
|
|
|
switch (LOAD_U8(h->type))
|
2023-10-25 10:41:23 +00:00
|
|
|
{
|
2022-09-20 12:28:57 +00:00
|
|
|
case AGENTX_GET_PDU:
|
|
|
|
case AGENTX_GET_NEXT_PDU:
|
2022-09-30 07:36:09 +00:00
|
|
|
case AGENTX_GET_BULK_PDU:
|
2024-01-23 23:23:31 +00:00
|
|
|
return parse_gets_pdu(p, pkt);
|
2023-03-14 13:10:08 +00:00
|
|
|
|
|
|
|
case AGENTX_CLOSE_PDU:
|
2024-01-23 23:23:31 +00:00
|
|
|
return parse_close_pdu(p, pkt);
|
2023-10-19 14:27:04 +00:00
|
|
|
|
|
|
|
case AGENTX_TEST_SET_PDU:
|
2024-01-23 23:23:31 +00:00
|
|
|
return parse_test_set_pdu(p, pkt);
|
2023-10-19 14:27:04 +00:00
|
|
|
|
|
|
|
case AGENTX_COMMIT_SET_PDU:
|
2024-01-23 23:23:31 +00:00
|
|
|
return parse_commit_set_pdu(p, pkt);
|
2023-10-19 14:27:04 +00:00
|
|
|
|
|
|
|
case AGENTX_UNDO_SET_PDU:
|
2024-01-23 23:23:31 +00:00
|
|
|
return parse_undo_set_pdu(p, pkt);
|
2023-10-19 14:27:04 +00:00
|
|
|
|
|
|
|
case AGENTX_CLEANUP_SET_PDU:
|
2024-01-23 23:23:31 +00:00
|
|
|
return parse_cleanup_set_pdu(p, pkt);
|
2023-03-14 13:10:08 +00:00
|
|
|
|
2022-08-10 15:31:32 +00:00
|
|
|
default:
|
2024-01-10 11:21:46 +00:00
|
|
|
/* We reset the connection for malformed packet (Unknown packet type) */
|
2024-07-24 11:38:36 +00:00
|
|
|
TRACE(D_PACKETS, "SNMP received unknown packet with type %u", LOAD_U8(h->type));
|
|
|
|
snmp_reset(p);
|
2024-01-10 11:21:46 +00:00
|
|
|
return 0;
|
2023-09-04 07:25:51 +00:00
|
|
|
}
|
2023-10-19 14:27:04 +00:00
|
|
|
}
|
|
|
|
|
2022-08-10 15:31:32 +00:00
|
|
|
|
2023-11-08 09:55:42 +00:00
|
|
|
/*
|
|
|
|
* parse_response - parse an agentx-Response-PDU
|
|
|
|
* @p: SNMP protocol instance
|
|
|
|
* @res: pointer of agentx-Response-PDU header in RX-buffer
|
|
|
|
*
|
|
|
|
* Return number of bytes parsed from RX-buffer.
|
|
|
|
*/
|
2023-03-14 13:10:08 +00:00
|
|
|
static uint
|
2024-01-23 23:23:31 +00:00
|
|
|
parse_response(struct snmp_proto *p, byte *res)
|
2022-08-10 15:31:32 +00:00
|
|
|
{
|
2023-03-14 13:10:08 +00:00
|
|
|
struct agentx_response *r = (void *) res;
|
2024-01-10 11:21:46 +00:00
|
|
|
struct agentx_header *h = (void *) r;
|
2022-08-10 15:31:32 +00:00
|
|
|
|
2023-11-15 11:37:10 +00:00
|
|
|
// todo reject not compiled byte order
|
|
|
|
uint pkt_size = LOAD_U32(h->payload);
|
2022-09-06 16:04:29 +00:00
|
|
|
|
2023-10-19 14:27:04 +00:00
|
|
|
switch (r->error)
|
|
|
|
{
|
|
|
|
case AGENTX_RES_NO_ERROR:
|
2024-01-10 11:21:46 +00:00
|
|
|
TRACE(D_PACKETS, "SNMP received agetnx-Response-PDU");
|
2024-01-23 23:23:31 +00:00
|
|
|
do_response(p, res);
|
2023-10-19 14:27:04 +00:00
|
|
|
break;
|
2022-09-06 16:04:29 +00:00
|
|
|
|
2023-10-19 14:27:04 +00:00
|
|
|
/* Registration errors */
|
|
|
|
case AGENTX_RES_DUPLICATE_REGISTER:
|
|
|
|
case AGENTX_RES_REQUEST_DENIED:
|
2023-11-15 14:03:55 +00:00
|
|
|
case AGENTX_RES_UNKNOWN_REGISTER:
|
2024-01-23 23:23:31 +00:00
|
|
|
// TODO more direct path to mib-specific code
|
2024-01-10 11:21:46 +00:00
|
|
|
TRACE(D_PACKETS, "SNMP received agentx-Response-PDU with error %u", r->error);
|
2024-01-23 23:23:31 +00:00
|
|
|
byte *pkt = res + sizeof(struct agentx_response);
|
2024-07-23 11:48:20 +00:00
|
|
|
struct oid *failed = (struct oid *) pkt;
|
|
|
|
snmp_register_ack(p, r, failed);
|
2023-10-19 14:27:04 +00:00
|
|
|
break;
|
|
|
|
|
2023-11-15 14:03:55 +00:00
|
|
|
/*
|
|
|
|
* We found ourselves in an unexpected situation. To enter a well defined
|
|
|
|
* state as well as give the AgentX master agent room to fix the errors on
|
|
|
|
* his side, we perform a hard reset of the connections.
|
|
|
|
*/
|
|
|
|
case AGENTX_RES_NOT_OPEN:
|
|
|
|
case AGENTX_RES_OPEN_FAILED:
|
2023-10-19 14:27:04 +00:00
|
|
|
case AGENTX_RES_UNKNOWN_AGENT_CAPS:
|
2023-11-15 14:03:55 +00:00
|
|
|
case AGENTX_RES_UNSUPPORTED_CONTEXT: /* currently we don't use contexts */
|
2023-10-19 14:27:04 +00:00
|
|
|
case AGENTX_RES_PARSE_ERROR:
|
|
|
|
case AGENTX_RES_PROCESSING_ERR:
|
|
|
|
default:
|
2024-07-24 11:38:36 +00:00
|
|
|
TRACE(D_PACKETS, "SNMP agentx-Response-PDU with unexepected error %u", r->error);
|
|
|
|
snmp_stop(p);
|
2023-10-19 14:27:04 +00:00
|
|
|
break;
|
|
|
|
}
|
2022-09-06 16:04:29 +00:00
|
|
|
|
2023-07-26 12:30:34 +00:00
|
|
|
return pkt_size + AGENTX_HEADER_SIZE;
|
2022-09-06 16:04:29 +00:00
|
|
|
}
|
|
|
|
|
2023-11-08 09:55:42 +00:00
|
|
|
/*
|
|
|
|
* snmp_register_mibs - register all MIB subtrees
|
|
|
|
* @p: SNMP protocol instance
|
|
|
|
*/
|
2023-11-15 14:03:55 +00:00
|
|
|
void
|
2023-07-26 12:34:01 +00:00
|
|
|
snmp_register_mibs(struct snmp_proto *p)
|
|
|
|
{
|
2024-05-24 13:20:30 +00:00
|
|
|
snmp_bgp4_register(p);
|
2022-12-10 17:08:00 +00:00
|
|
|
}
|
|
|
|
|
2023-11-08 09:55:42 +00:00
|
|
|
/*
|
|
|
|
* do_response - act on agentx-Response-PDU and protocol state
|
|
|
|
* @p: SNMP protocol instance
|
2024-01-23 23:23:31 +00:00
|
|
|
* @pkt: RX-buffer with PDU bytes
|
2023-11-08 09:55:42 +00:00
|
|
|
*
|
|
|
|
* Return number of bytes parsed from RX-buffer.
|
|
|
|
*/
|
2023-03-14 13:10:08 +00:00
|
|
|
static void
|
2024-01-23 23:23:31 +00:00
|
|
|
do_response(struct snmp_proto *p, byte *pkt)
|
2022-09-06 16:04:29 +00:00
|
|
|
{
|
2024-01-23 23:23:31 +00:00
|
|
|
struct agentx_response *r = (void *) pkt;
|
2024-01-10 11:21:46 +00:00
|
|
|
struct agentx_header *h = (void *) r;
|
2022-12-17 17:16:19 +00:00
|
|
|
|
2022-09-06 16:04:29 +00:00
|
|
|
switch (p->state)
|
2022-08-10 15:31:32 +00:00
|
|
|
{
|
2022-09-06 16:04:29 +00:00
|
|
|
case SNMP_INIT:
|
2023-09-04 07:25:51 +00:00
|
|
|
case SNMP_LOCKED:
|
2023-11-08 09:55:42 +00:00
|
|
|
/* silent drop of received packet */
|
2023-09-04 07:25:51 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SNMP_OPEN:
|
2023-11-08 09:55:42 +00:00
|
|
|
/* copy session info from received packet */
|
2023-11-15 11:37:10 +00:00
|
|
|
p->session_id = LOAD_U32(h->session_id);
|
2023-07-26 12:30:34 +00:00
|
|
|
refresh_ids(p, h);
|
2022-09-06 16:04:29 +00:00
|
|
|
|
2023-11-15 14:03:55 +00:00
|
|
|
tm_start(p->ping_timer, 0);
|
|
|
|
|
2023-09-04 07:25:51 +00:00
|
|
|
/* the state needs to be changed before sending registering PDUs to
|
2022-12-17 17:16:19 +00:00
|
|
|
* use correct do_response action on them
|
|
|
|
*/
|
2023-11-15 14:03:55 +00:00
|
|
|
snmp_set_state(p, SNMP_REGISTER);
|
2022-08-10 15:31:32 +00:00
|
|
|
break;
|
2022-09-06 16:04:29 +00:00
|
|
|
|
2023-10-18 16:06:24 +00:00
|
|
|
case SNMP_REGISTER:;
|
2024-01-23 23:23:31 +00:00
|
|
|
pkt += AGENTX_HEADER_SIZE;
|
2023-09-11 11:06:20 +00:00
|
|
|
|
2024-07-23 11:48:20 +00:00
|
|
|
const struct oid *oid = (struct oid *) pkt;
|
|
|
|
snmp_register_ack(p, r, oid);
|
2023-09-11 11:06:20 +00:00
|
|
|
|
2023-11-15 14:03:55 +00:00
|
|
|
if (p->registrations_to_ack == 0)
|
|
|
|
snmp_set_state(p, SNMP_CONN);
|
2022-08-10 15:31:32 +00:00
|
|
|
break;
|
2022-09-06 16:04:29 +00:00
|
|
|
|
|
|
|
case SNMP_CONN:
|
|
|
|
break;
|
|
|
|
|
2022-12-17 17:16:19 +00:00
|
|
|
case SNMP_STOP:
|
|
|
|
break;
|
|
|
|
|
2022-09-06 16:04:29 +00:00
|
|
|
default:
|
|
|
|
die("unkonwn SNMP state");
|
2022-08-10 15:31:32 +00:00
|
|
|
}
|
2022-09-06 16:04:29 +00:00
|
|
|
}
|
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
static inline struct oid *
|
|
|
|
snmp_oid_prefixize_unsafe(struct oid *dest, const struct oid *src)
|
|
|
|
{
|
|
|
|
u8 subids = LOAD_U8(src->n_subid) - 5;
|
|
|
|
dest->n_subid = subids;
|
|
|
|
STORE_U8(dest->prefix, (u8) LOAD_U32(src->ids[ARRAY_SIZE(snmp_internet)]));
|
|
|
|
STORE_U8(dest->include, (LOAD_U8(src->include)) ? 1 : 0);
|
|
|
|
STORE_U8(dest->reserved, 0);
|
|
|
|
|
|
|
|
/* The LOAD_U32() and STORE_U32() cancel out */
|
|
|
|
memcpy(&dest->ids[0], &src->ids[5], subids * sizeof(u32));
|
|
|
|
|
|
|
|
return dest;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* snmp_vb_to_tx - create varbind from RX buffer OID
|
|
|
|
* @c: PDU context
|
2024-07-23 11:48:20 +00:00
|
|
|
* @oid: object identifier located in RX buffer
|
2024-04-22 10:55:33 +00:00
|
|
|
*
|
|
|
|
* Create NULL initialized VarBind inside TX buffer (from @c) whose vb->name is
|
2024-07-04 14:33:44 +00:00
|
|
|
* @oid. The @oid prefixed if possible. The result is stored in @c->sr_vb_start.
|
2024-04-22 10:55:33 +00:00
|
|
|
*/
|
2024-07-04 14:33:44 +00:00
|
|
|
void
|
2024-07-23 11:48:20 +00:00
|
|
|
snmp_vb_to_tx(struct snmp_pdu *c, const struct oid *oid)
|
2024-04-22 10:55:33 +00:00
|
|
|
{
|
|
|
|
uint vb_hdr_size = snmp_varbind_hdr_size_from_oid(oid);
|
2024-07-23 11:48:20 +00:00
|
|
|
if (snmp_tbuf_reserve(c, vb_hdr_size))
|
2024-07-04 14:33:44 +00:00
|
|
|
snmp_log("SNMP vb_to_tx small buffer");
|
2024-04-22 10:55:33 +00:00
|
|
|
|
|
|
|
ASSERT(c->size >= vb_hdr_size);
|
2024-07-24 11:38:36 +00:00
|
|
|
struct agentx_varbind *vb = (struct agentx_varbind *) c->buffer;
|
2024-04-22 10:55:33 +00:00
|
|
|
ADVANCE(c->buffer, c->size, sizeof(struct agentx_varbind) - sizeof(struct oid));
|
|
|
|
/* Move the c->buffer so that is points at &vb->name */
|
|
|
|
snmp_set_varbind_type(vb, AGENTX_NULL);
|
|
|
|
|
|
|
|
if (snmp_oid_is_prefixable(oid) && !snmp_oid_is_prefixed(oid))
|
|
|
|
{
|
|
|
|
u8 subids = LOAD_U8(oid->n_subid) - 5;
|
|
|
|
ADVANCE(c->buffer, c->size, snmp_oid_size_from_len(subids));
|
|
|
|
(void) snmp_oid_prefixize_unsafe(&vb->name, oid);
|
2024-07-04 14:33:44 +00:00
|
|
|
|
|
|
|
c->sr_vb_start = vb;
|
|
|
|
return;
|
2024-04-22 10:55:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ADVANCE(c->buffer, c->size, snmp_oid_size(oid));
|
|
|
|
snmp_oid_copy2(&vb->name, oid);
|
|
|
|
|
2024-07-04 14:33:44 +00:00
|
|
|
c->sr_vb_start = vb;
|
2024-04-22 10:55:33 +00:00
|
|
|
}
|
2023-03-14 13:10:08 +00:00
|
|
|
|
2023-11-08 09:55:42 +00:00
|
|
|
/*
|
|
|
|
* update_packet_size - set PDU size
|
|
|
|
* @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).
|
|
|
|
*/
|
2023-08-08 17:00:54 +00:00
|
|
|
static inline uint
|
2024-01-23 23:23:31 +00:00
|
|
|
update_packet_size(struct agentx_header *start, byte *end)
|
2023-07-26 12:30:34 +00:00
|
|
|
{
|
2024-01-10 11:21:46 +00:00
|
|
|
uint s = snmp_pkt_len((byte *) start, end);
|
|
|
|
STORE_U32(start->payload, s);
|
2023-08-08 17:00:54 +00:00
|
|
|
return AGENTX_HEADER_SIZE + s;
|
2023-07-26 12:30:34 +00:00
|
|
|
}
|
|
|
|
|
2023-11-08 09:55:42 +00:00
|
|
|
/*
|
|
|
|
* response_err_ind - update response error and index
|
2024-01-10 11:21:46 +00:00
|
|
|
* @p: SNMP protocol instance
|
2023-11-08 09:55:42 +00:00
|
|
|
* @res: response PDU header
|
|
|
|
* @err: error status
|
|
|
|
* @ind: index of error, ignored for noAgentXError
|
|
|
|
*
|
2024-01-10 11:21:46 +00:00
|
|
|
* Update agentx-Response-PDU header fields res.error and it's res.index. If the
|
|
|
|
* error is not noError, also set the corrent response PDU payload size.
|
2023-11-08 09:55:42 +00:00
|
|
|
*/
|
2023-07-26 12:30:34 +00:00
|
|
|
static inline void
|
2024-01-10 11:21:46 +00:00
|
|
|
response_err_ind(struct snmp_proto *p, struct agentx_response *res, enum agentx_response_errs err, u16 ind)
|
2023-07-26 12:30:34 +00:00
|
|
|
{
|
2024-07-24 11:38:36 +00:00
|
|
|
STORE_U16(res->error, (u16) err);
|
2024-01-10 11:21:46 +00:00
|
|
|
// TODO deal with auto-incrementing of snmp_pdu context c.ind
|
|
|
|
if (err != AGENTX_RES_NO_ERROR && err != AGENTX_RES_GEN_ERROR)
|
|
|
|
{
|
|
|
|
TRACE(D_PACKETS, "Last PDU resulted in error %u", err);
|
2024-07-24 11:38:36 +00:00
|
|
|
STORE_U16(res->index, ind);
|
2024-01-10 11:21:46 +00:00
|
|
|
TRACE(D_PACKETS, "Storing packet size %u (was %u)", sizeof(struct agentx_response) - AGENTX_HEADER_SIZE, LOAD_U32(res->h.payload));
|
|
|
|
STORE_U32(res->h.payload,
|
|
|
|
sizeof(struct agentx_response) - AGENTX_HEADER_SIZE);
|
|
|
|
}
|
|
|
|
else if (err == AGENTX_RES_GEN_ERROR)
|
|
|
|
{
|
2024-07-04 14:33:44 +00:00
|
|
|
TRACE(D_PACKETS, "Last PDU resulted in error %u genErr", err);
|
2024-07-24 11:38:36 +00:00
|
|
|
STORE_U16(res->index, 0);
|
2024-01-10 11:21:46 +00:00
|
|
|
TRACE(D_PACKETS, "Storing packet size %u (was %u)", sizeof(struct agentx_response) - AGENTX_HEADER_SIZE, LOAD_U32(res->h.payload));
|
|
|
|
STORE_U32(res->h.payload,
|
|
|
|
sizeof(struct agentx_response) - AGENTX_HEADER_SIZE);
|
|
|
|
}
|
2023-07-26 12:30:34 +00:00
|
|
|
else
|
2024-07-24 11:38:36 +00:00
|
|
|
STORE_U16(res->index, 0);
|
2023-07-26 12:30:34 +00:00
|
|
|
}
|
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
static inline uint
|
2024-01-23 23:23:31 +00:00
|
|
|
parse_gets_error(struct snmp_proto *p, struct snmp_pdu *c, uint len)
|
|
|
|
{
|
|
|
|
TRACE(D_PACKETS, "SNMP error %u while parsing gets PDU", c->error);
|
|
|
|
if (c->index > UINT16_MAX)
|
|
|
|
snmp_simple_response(p, AGENTX_RES_GEN_ERROR, UINT16_MAX);
|
|
|
|
else
|
|
|
|
snmp_simple_response(p, AGENTX_RES_GEN_ERROR, c->index);
|
|
|
|
|
|
|
|
return len + AGENTX_HEADER_SIZE;
|
|
|
|
}
|
2024-05-24 13:20:30 +00:00
|
|
|
|
2024-07-04 14:33:44 +00:00
|
|
|
/*
|
|
|
|
* AgentX GetPDU, GetNextPDU and GetBulkPDU
|
|
|
|
*/
|
2024-07-23 11:48:20 +00:00
|
|
|
|
|
|
|
/* agentx-Get-PDU */
|
2024-07-04 14:33:44 +00:00
|
|
|
void
|
|
|
|
snmp_get_pdu(struct snmp_proto *p, struct snmp_pdu *c, const struct oid *o_start, struct mib_walk_state *walk)
|
2024-05-24 13:20:30 +00:00
|
|
|
{
|
2024-07-04 14:33:44 +00:00
|
|
|
snmp_log("snmp_get_pdu()");
|
2024-05-24 13:20:30 +00:00
|
|
|
|
2024-07-04 14:33:44 +00:00
|
|
|
struct mib_leaf *leaf;
|
2024-07-17 11:03:26 +00:00
|
|
|
leaf = snmp_walk_init(p->mib_tree, walk, o_start, c);
|
2024-05-24 13:20:30 +00:00
|
|
|
|
2024-07-04 14:33:44 +00:00
|
|
|
snmp_log("found node %p", leaf);
|
2024-05-24 13:20:30 +00:00
|
|
|
|
2024-07-04 14:33:44 +00:00
|
|
|
enum snmp_search_res res;
|
2024-07-17 11:03:26 +00:00
|
|
|
res = snmp_walk_fill(leaf, walk, c);
|
2024-07-04 14:33:44 +00:00
|
|
|
|
|
|
|
snmp_log("fill result %u", res);
|
2024-05-24 13:20:30 +00:00
|
|
|
|
2024-07-04 14:33:44 +00:00
|
|
|
if (res != SNMP_SEARCH_OK)
|
|
|
|
snmp_set_varbind_type(c->sr_vb_start, snmp_search_res_to_type(res));
|
2024-05-24 13:20:30 +00:00
|
|
|
}
|
|
|
|
|
2024-07-23 11:48:20 +00:00
|
|
|
/* agentx-GetNext-PDU */
|
2024-05-24 13:20:30 +00:00
|
|
|
int
|
2024-07-04 14:33:44 +00:00
|
|
|
snmp_get_next_pdu(struct snmp_proto *p, struct snmp_pdu *c, const struct oid *o_start, struct mib_walk_state *walk)
|
2024-05-24 13:20:30 +00:00
|
|
|
{
|
2024-07-17 11:03:26 +00:00
|
|
|
(void) snmp_walk_init(p->mib_tree, walk, o_start, c);
|
|
|
|
struct mib_leaf *leaf = snmp_walk_next(p->mib_tree, walk, c);
|
2024-05-24 13:20:30 +00:00
|
|
|
|
|
|
|
enum snmp_search_res res;
|
2024-07-17 11:03:26 +00:00
|
|
|
res = snmp_walk_fill(leaf, walk, c);
|
2024-05-24 13:20:30 +00:00
|
|
|
|
|
|
|
if (res != SNMP_SEARCH_OK)
|
|
|
|
snmp_set_varbind_type(c->sr_vb_start, AGENTX_END_OF_MIB_VIEW);
|
|
|
|
|
|
|
|
return res == SNMP_SEARCH_OK;
|
|
|
|
}
|
|
|
|
|
2024-07-23 11:48:20 +00:00
|
|
|
/* agentx-GetBulk-PDU */
|
2024-05-24 13:20:30 +00:00
|
|
|
void
|
2024-07-04 14:33:44 +00:00
|
|
|
snmp_get_bulk_pdu(struct snmp_proto *p, struct snmp_pdu *c, const struct oid *o_start, struct mib_walk_state *walk, struct agentx_bulk_state *bulk)
|
2024-05-24 13:20:30 +00:00
|
|
|
{
|
|
|
|
if (c->index >= bulk->getbulk.non_repeaters)
|
|
|
|
bulk->repeaters++;
|
|
|
|
|
|
|
|
// store the o_start and o_end
|
|
|
|
|
2024-07-04 14:33:44 +00:00
|
|
|
bulk->has_any |= snmp_get_next_pdu(p, c, o_start, walk);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline const struct oid *
|
|
|
|
snmp_load_oids(byte **pkt_ptr, uint *pkt_sz, struct snmp_pdu *c)
|
|
|
|
{
|
|
|
|
byte *pkt = *pkt_ptr;
|
|
|
|
uint pkt_size = *pkt_sz;
|
|
|
|
|
|
|
|
uint sz;
|
|
|
|
const struct oid *start = (const struct oid *) pkt;
|
|
|
|
|
|
|
|
if ((sz = snmp_oid_size(start)) > pkt_size)
|
|
|
|
{
|
|
|
|
snmp_log("load_oids start %u / %u", sz, pkt_size);
|
|
|
|
c->error = AGENTX_RES_PARSE_ERROR;
|
|
|
|
*pkt_ptr = pkt;
|
|
|
|
*pkt_sz = pkt_size;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
ADVANCE(pkt, pkt_size, sz);
|
|
|
|
|
|
|
|
const struct oid *end = (const struct oid *) pkt;
|
|
|
|
if ((sz = snmp_oid_size(end)) > pkt_size)
|
|
|
|
{
|
|
|
|
snmp_log("load_oids end %u / %u", sz, pkt_size);
|
|
|
|
c->error = AGENTX_RES_PARSE_ERROR;
|
|
|
|
*pkt_ptr = pkt;
|
|
|
|
*pkt_sz = pkt_size;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
ADVANCE(pkt, pkt_size, sz);
|
|
|
|
|
|
|
|
if (!snmp_is_oid_empty(end) &&
|
|
|
|
snmp_oid_compare(start, end) > 0)
|
|
|
|
{
|
|
|
|
c->error = AGENTX_RES_GEN_ERROR;
|
|
|
|
*pkt_ptr = pkt;
|
|
|
|
*pkt_sz = pkt_size;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
ASSERT(start != NULL);
|
|
|
|
ASSERT(end != NULL);
|
|
|
|
|
|
|
|
c->sr_o_end = end;
|
|
|
|
*pkt_ptr = pkt;
|
|
|
|
*pkt_sz = pkt_size;
|
|
|
|
return start;
|
2024-05-24 13:20:30 +00:00
|
|
|
}
|
|
|
|
|
2023-11-08 09:55:42 +00:00
|
|
|
/*
|
|
|
|
* parse_gets_pdu - parse received gets PDUs
|
|
|
|
* @p: SNMP protocol instance
|
|
|
|
* @pkt_start: pointer to first byte of received PDU
|
|
|
|
*
|
|
|
|
* Gets PDUs are agentx-Get-PDU, agentx-GetNext-PDU, agentx-GetBulk-PDU.
|
|
|
|
*
|
|
|
|
* Return number of bytes parsed from RX-buffer
|
|
|
|
*/
|
2023-07-26 12:30:34 +00:00
|
|
|
static uint
|
2024-01-23 23:23:31 +00:00
|
|
|
parse_gets_pdu(struct snmp_proto *p, byte * const pkt_start)
|
2023-07-26 12:30:34 +00:00
|
|
|
{
|
2024-07-04 14:33:44 +00:00
|
|
|
snmp_log("parse_gets_pdu msg");
|
2023-09-11 11:06:20 +00:00
|
|
|
// TODO checks for c.size underflow
|
2024-05-24 13:20:30 +00:00
|
|
|
struct mib_walk_state walk;
|
2023-07-26 12:30:34 +00:00
|
|
|
byte *pkt = pkt_start;
|
|
|
|
|
|
|
|
struct agentx_header *h = (void *) pkt;
|
2024-01-23 23:23:31 +00:00
|
|
|
pkt += AGENTX_HEADER_SIZE;
|
2023-11-15 11:37:10 +00:00
|
|
|
uint pkt_size = LOAD_U32(h->payload);
|
2023-07-26 12:30:34 +00:00
|
|
|
|
|
|
|
sock *sk = p->sock;
|
2023-11-15 10:29:19 +00:00
|
|
|
struct snmp_pdu c;
|
2024-07-17 11:03:26 +00:00
|
|
|
snmp_pdu_context(&c, p, sk);
|
2023-07-26 12:30:34 +00:00
|
|
|
|
2023-10-18 11:30:14 +00:00
|
|
|
/*
|
|
|
|
* Get-Bulk processing stops if all the varbind have type END_OF_MIB_VIEW
|
|
|
|
* has_any is true if some varbind has type other than END_OF_MIB_VIEW
|
|
|
|
*/
|
2024-07-04 14:33:44 +00:00
|
|
|
struct agentx_bulk_state bulk_state = { 0 };
|
2023-09-04 07:25:51 +00:00
|
|
|
if (h->type == AGENTX_GET_BULK_PDU)
|
|
|
|
{
|
|
|
|
if (pkt_size < sizeof(struct agentx_getbulk))
|
|
|
|
{
|
2024-07-04 14:33:44 +00:00
|
|
|
snmp_log("parse_gets GetBulkPDU prepare");
|
2023-09-04 07:25:51 +00:00
|
|
|
c.error = AGENTX_RES_PARSE_ERROR;
|
2023-10-25 10:41:23 +00:00
|
|
|
c.index = 0;
|
2024-01-23 23:23:31 +00:00
|
|
|
return parse_gets_error(p, &c, pkt_size);
|
2023-09-04 07:25:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
struct agentx_getbulk *bulk_info = (void *) pkt;
|
|
|
|
ADVANCE(pkt, pkt_size, sizeof(struct agentx_getbulk));
|
|
|
|
|
|
|
|
bulk_state = (struct agentx_bulk_state) {
|
|
|
|
.getbulk = {
|
2023-11-15 11:37:10 +00:00
|
|
|
.non_repeaters = LOAD_U32(bulk_info->non_repeaters),
|
|
|
|
.max_repetitions = LOAD_U32(bulk_info->max_repetitions),
|
2023-09-04 07:25:51 +00:00
|
|
|
},
|
2023-10-18 11:30:14 +00:00
|
|
|
/* In contrast to the RFC, we use 0-based indices. */
|
|
|
|
.index = 0,
|
|
|
|
.repetition = 0,
|
2024-05-24 13:20:30 +00:00
|
|
|
.has_any = 0,
|
2023-09-04 07:25:51 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2023-07-26 12:30:34 +00:00
|
|
|
struct agentx_response *response_header = prepare_response(p, &c);
|
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
lp_state tmps;
|
|
|
|
lp_save(tmp_linpool, &tmps);
|
2024-01-23 23:23:31 +00:00
|
|
|
while (c.error == AGENTX_RES_NO_ERROR && pkt_size > 0)
|
2023-07-26 12:30:34 +00:00
|
|
|
{
|
2024-04-22 10:55:33 +00:00
|
|
|
lp_restore(tmp_linpool, &tmps);
|
|
|
|
|
2024-07-04 14:33:44 +00:00
|
|
|
const struct oid *start_rx;
|
|
|
|
if (!(start_rx = snmp_load_oids(&pkt, &pkt_size, &c)))
|
2023-07-26 12:30:34 +00:00
|
|
|
{
|
2024-07-04 14:33:44 +00:00
|
|
|
snmp_log("snmp_load_oid ends with an error");
|
2024-01-23 23:23:31 +00:00
|
|
|
return parse_gets_error(p, &c, pkt_size);
|
2023-07-26 12:30:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
switch (h->type)
|
|
|
|
{
|
|
|
|
case AGENTX_GET_PDU:
|
2024-07-04 14:33:44 +00:00
|
|
|
snmp_get_pdu(p, &c, start_rx, &walk);
|
2023-07-26 12:30:34 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case AGENTX_GET_NEXT_PDU:
|
2024-07-04 14:33:44 +00:00
|
|
|
snmp_get_next_pdu(p, &c, start_rx, &walk);
|
2023-07-26 12:30:34 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case AGENTX_GET_BULK_PDU:
|
2024-07-04 14:33:44 +00:00
|
|
|
snmp_get_bulk_pdu(p, &c, start_rx, &walk, &bulk_state);
|
2023-07-26 12:30:34 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2024-07-04 14:33:44 +00:00
|
|
|
die("implementation failure");
|
2023-07-26 12:30:34 +00:00
|
|
|
}
|
|
|
|
|
2024-05-24 13:20:30 +00:00
|
|
|
c.sr_vb_start = NULL;
|
|
|
|
c.sr_o_end = NULL;
|
2023-07-26 12:30:34 +00:00
|
|
|
|
2023-10-25 10:41:23 +00:00
|
|
|
c.index++;
|
2023-07-26 12:30:34 +00:00
|
|
|
} /* while (c.error == AGENTX_RES_NO_ERROR && size > 0) */
|
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
lp_restore(tmp_linpool, &tmps);
|
|
|
|
|
2023-10-18 11:30:14 +00:00
|
|
|
if (h->type == AGENTX_GET_BULK_PDU)
|
|
|
|
{
|
2024-07-23 11:48:20 +00:00
|
|
|
// TODO: an error for now
|
2023-10-18 11:30:14 +00:00
|
|
|
}
|
|
|
|
|
2023-09-04 12:01:08 +00:00
|
|
|
/* We update the error, index pair on the beginning of the packet. */
|
2024-01-23 23:23:31 +00:00
|
|
|
response_err_ind(p, response_header, c.error, c.index + 1);
|
|
|
|
uint s = update_packet_size(&response_header->h, c.buffer);
|
2023-09-04 07:25:51 +00:00
|
|
|
|
2023-09-04 12:01:08 +00:00
|
|
|
/* We send the message in TX-buffer. */
|
2023-10-19 14:20:37 +00:00
|
|
|
sk_send(sk, s);
|
2024-05-24 13:20:30 +00:00
|
|
|
|
2024-07-22 16:17:16 +00:00
|
|
|
snmp_log("gets send %t", current_time());
|
|
|
|
|
2023-09-04 07:25:51 +00:00
|
|
|
// TODO think through the error state
|
|
|
|
|
2023-09-04 12:01:08 +00:00
|
|
|
/* number of bytes parsed from RX-buffer */
|
2024-01-23 23:23:31 +00:00
|
|
|
return pkt - pkt_start;
|
2023-07-26 12:30:34 +00:00
|
|
|
}
|
|
|
|
|
2023-11-08 09:55:42 +00:00
|
|
|
/*
|
|
|
|
* snmp_start_subagent - send session open request
|
|
|
|
* @p: SNMP protocol instance
|
|
|
|
*
|
|
|
|
* Send agentx-Open-PDU with configured OID and string description.
|
|
|
|
*/
|
2022-08-02 14:04:25 +00:00
|
|
|
void
|
2022-08-10 15:31:32 +00:00
|
|
|
snmp_start_subagent(struct snmp_proto *p)
|
2022-08-02 14:04:25 +00:00
|
|
|
{
|
2024-01-10 11:21:46 +00:00
|
|
|
ASSUME(p->state == SNMP_OPEN);
|
|
|
|
|
2023-09-04 07:25:51 +00:00
|
|
|
/* blank oid means unsupported */
|
2024-07-22 16:17:16 +00:00
|
|
|
STATIC_OID(0) blank = { 0 };
|
|
|
|
open_pdu(p, (struct oid *) &blank);
|
2022-08-02 14:04:25 +00:00
|
|
|
}
|
|
|
|
|
2023-11-08 09:55:42 +00:00
|
|
|
/*
|
|
|
|
* snmp_stop_subagent - close established session
|
|
|
|
* @p: SNMP protocol instance
|
|
|
|
*
|
|
|
|
* Send agentx-Close-PDU on established session.
|
|
|
|
*/
|
2022-08-02 14:04:25 +00:00
|
|
|
void
|
2022-08-10 15:31:32 +00:00
|
|
|
snmp_stop_subagent(struct snmp_proto *p)
|
2022-08-02 14:04:25 +00:00
|
|
|
{
|
2023-11-15 14:03:55 +00:00
|
|
|
tm_stop(p->ping_timer);
|
2024-01-23 23:23:31 +00:00
|
|
|
/* This cause problems with net-snmp daemon witch halts afterwards */
|
2024-07-09 14:56:16 +00:00
|
|
|
close_pdu(p, AGENTX_CLOSE_SHUTDOWN);
|
2022-08-10 15:31:32 +00:00
|
|
|
}
|
2022-08-02 14:04:25 +00:00
|
|
|
|
2023-11-08 09:55:42 +00:00
|
|
|
/*
|
|
|
|
* snmp_rx - handle received PDUs in RX-buffer in normal operation
|
|
|
|
* @sk: communication socket
|
|
|
|
* @size: number of bytes received
|
|
|
|
*/
|
2023-03-14 13:10:08 +00:00
|
|
|
int
|
|
|
|
snmp_rx(sock *sk, uint size)
|
|
|
|
{
|
2024-07-24 11:38:36 +00:00
|
|
|
struct snmp_proto *p = (struct snmp_proto *) sk->data;
|
2023-03-14 13:10:08 +00:00
|
|
|
byte *pkt_start = sk->rbuf;
|
2023-07-26 12:30:34 +00:00
|
|
|
byte *end = pkt_start + size;
|
|
|
|
|
2024-01-23 23:23:31 +00:00
|
|
|
while (snmp_is_active(p) && end >= pkt_start + AGENTX_HEADER_SIZE)
|
2023-03-14 13:10:08 +00:00
|
|
|
{
|
2024-01-23 23:23:31 +00:00
|
|
|
uint parsed_len = parse_pkt(p, pkt_start, size);
|
2023-07-26 12:30:34 +00:00
|
|
|
|
2023-03-14 13:10:08 +00:00
|
|
|
if (parsed_len == 0)
|
|
|
|
break;
|
|
|
|
|
|
|
|
pkt_start += parsed_len;
|
|
|
|
size -= parsed_len;
|
|
|
|
}
|
|
|
|
|
2024-01-23 23:23:31 +00:00
|
|
|
/* We flush the RX-buffer on errors */
|
|
|
|
if (!snmp_is_active(p) || pkt_start == end)
|
|
|
|
return 1; /* The whole RX-buffer was consumed */
|
2023-03-14 13:10:08 +00:00
|
|
|
|
2024-01-23 23:23:31 +00:00
|
|
|
/* Incomplete packet parsing */
|
|
|
|
memmove(sk->rbuf, pkt_start, size);
|
|
|
|
sk->rpos = sk->rbuf + size;
|
|
|
|
return 0;
|
2023-03-14 13:10:08 +00:00
|
|
|
}
|
2022-08-02 14:04:25 +00:00
|
|
|
|
2024-01-10 11:21:46 +00:00
|
|
|
/*
|
|
|
|
* snmp_tx - handle TX-buffer
|
|
|
|
* @sk: communication socket owned by SNMP protocol instance
|
|
|
|
*
|
|
|
|
* The snmp_tx hook is used only to delay the processing in cases we don't have
|
|
|
|
* enough space in TX-buffer. Therefore we simply call the snmp_rx hook.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
snmp_tx(sock *sk)
|
|
|
|
{
|
2024-07-04 14:33:44 +00:00
|
|
|
snmp_log("snmp_tx()");
|
2024-01-10 11:21:46 +00:00
|
|
|
/* We still not have enough space */
|
|
|
|
if (!space_for_response(sk))
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* There is nothing to process, no bytes in RX-buffer */
|
|
|
|
if (sk_tx_buffer_empty(sk))
|
|
|
|
return;
|
|
|
|
|
|
|
|
snmp_rx(sk, sk->tpos - sk->tbuf);
|
|
|
|
}
|
|
|
|
|
2023-10-25 10:56:23 +00:00
|
|
|
|
2023-11-08 09:55:42 +00:00
|
|
|
/*
|
|
|
|
* snmp_ping - send an agentx-Ping-PDU
|
|
|
|
* @p: SNMP protocol instance
|
|
|
|
*/
|
2022-09-06 16:04:29 +00:00
|
|
|
void
|
|
|
|
snmp_ping(struct snmp_proto *p)
|
2022-08-02 14:04:25 +00:00
|
|
|
{
|
2024-01-10 11:21:46 +00:00
|
|
|
if (!snmp_is_active(p))
|
|
|
|
return;
|
|
|
|
|
2022-08-10 15:31:32 +00:00
|
|
|
sock *sk = p->sock;
|
2023-11-15 10:29:19 +00:00
|
|
|
struct snmp_pdu c;
|
2024-07-17 11:03:26 +00:00
|
|
|
snmp_pdu_context(&c, p, sk);
|
2022-09-06 16:04:29 +00:00
|
|
|
|
2023-07-26 12:30:34 +00:00
|
|
|
if (c.size < AGENTX_HEADER_SIZE)
|
2023-11-16 06:11:14 +00:00
|
|
|
return;
|
|
|
|
|
2024-01-10 11:21:46 +00:00
|
|
|
int unused = sk->tbuf + sk->tbsize - c.buffer;
|
2024-01-23 23:23:31 +00:00
|
|
|
if (unused < AGENTX_HEADER_SIZE)
|
2024-01-10 11:21:46 +00:00
|
|
|
return;
|
2022-09-30 07:36:09 +00:00
|
|
|
|
2024-01-23 23:23:31 +00:00
|
|
|
struct agentx_header *h = (void *) c.buffer;
|
2023-07-26 12:30:34 +00:00
|
|
|
ADVANCE(c.buffer, c.size, AGENTX_HEADER_SIZE);
|
2023-11-15 11:37:10 +00:00
|
|
|
snmp_blank_header(h, AGENTX_PING_PDU);
|
2023-08-08 17:00:54 +00:00
|
|
|
p->packet_id++;
|
2024-07-04 14:33:44 +00:00
|
|
|
snmp_log("incrementing packet_id to %u (ping)", p->packet_id);
|
2023-11-15 11:37:10 +00:00
|
|
|
snmp_session(p, h);
|
2022-08-02 14:04:25 +00:00
|
|
|
|
2024-01-10 11:21:46 +00:00
|
|
|
/* sending only header */
|
2024-01-23 23:23:31 +00:00
|
|
|
uint s = update_packet_size(h, (byte *) h + AGENTX_HEADER_SIZE);
|
2023-09-11 11:06:20 +00:00
|
|
|
|
2023-10-19 14:20:37 +00:00
|
|
|
sk_send(sk, s);
|
2022-08-02 14:04:25 +00:00
|
|
|
}
|
2022-08-10 15:31:32 +00:00
|
|
|
|
2022-12-17 17:16:19 +00:00
|
|
|
/**
|
2023-07-26 12:30:34 +00:00
|
|
|
* snmp_search_check_end_oid - check if oid is before SearchRange end
|
2022-12-17 17:16:19 +00:00
|
|
|
*
|
|
|
|
* @found: best oid found in MIB tree
|
|
|
|
* @bound: upper bound specified in SearchRange
|
|
|
|
*
|
|
|
|
* check if found oid meet the SearchRange upper bound condition in
|
|
|
|
* lexicographical order, returns boolean value
|
|
|
|
*/
|
2023-11-08 09:55:42 +00:00
|
|
|
int
|
|
|
|
snmp_search_check_end_oid(const struct oid *found, const struct oid *bound)
|
2022-09-20 12:28:57 +00:00
|
|
|
{
|
2022-12-17 17:16:19 +00:00
|
|
|
if (snmp_is_oid_empty(bound))
|
|
|
|
return 1;
|
|
|
|
|
2023-07-26 12:30:34 +00:00
|
|
|
return (snmp_oid_compare(found, bound) < 0);
|
2022-12-17 17:16:19 +00:00
|
|
|
}
|
|
|
|
|
2023-11-08 09:55:42 +00:00
|
|
|
/*
|
2024-07-23 11:48:20 +00:00
|
|
|
* snmp_tbuf_reserve - TODO
|
2023-07-26 12:30:34 +00:00
|
|
|
*
|
|
|
|
*/
|
2024-07-23 11:48:20 +00:00
|
|
|
int
|
|
|
|
snmp_tbuf_reserve(struct snmp_pdu *c, size_t size)
|
2022-09-06 16:04:29 +00:00
|
|
|
{
|
2024-07-23 11:48:20 +00:00
|
|
|
if (size >= c->size)
|
|
|
|
{
|
|
|
|
struct snmp_proto *p = c->p;
|
|
|
|
sock *sk = p->sock;
|
2023-09-04 12:01:08 +00:00
|
|
|
|
2024-07-23 11:48:20 +00:00
|
|
|
int diff;
|
|
|
|
if (c->sr_vb_start != NULL)
|
|
|
|
diff = (char *) c->sr_vb_start - (char *) sk->tbuf;
|
2024-04-22 10:55:33 +00:00
|
|
|
|
2024-07-23 11:48:20 +00:00
|
|
|
snmp_log("snmp_tbuf_reserve()");
|
|
|
|
sk_set_tbsize(sk, sk->tbsize + 2048);
|
|
|
|
c->size += 2048;
|
2022-08-10 15:31:32 +00:00
|
|
|
|
2024-07-23 11:48:20 +00:00
|
|
|
if (c->sr_vb_start != NULL)
|
|
|
|
c->sr_vb_start = (struct agentx_varbind *) (sk->tbuf + diff);
|
|
|
|
|
|
|
|
return 1;
|
2024-07-09 14:30:04 +00:00
|
|
|
}
|
2024-07-23 11:48:20 +00:00
|
|
|
|
|
|
|
return 0;
|
2024-07-09 14:30:04 +00:00
|
|
|
}
|
|
|
|
|
2023-11-08 09:55:42 +00:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
2023-07-26 12:30:34 +00:00
|
|
|
static struct agentx_response *
|
2023-09-11 11:06:20 +00:00
|
|
|
prepare_response(struct snmp_proto *p, struct snmp_pdu *c)
|
2023-07-26 12:30:34 +00:00
|
|
|
{
|
2023-10-19 14:08:13 +00:00
|
|
|
struct agentx_response *r = (void *) c->buffer;
|
2024-01-23 23:23:31 +00:00
|
|
|
struct agentx_header *h = &r->h;
|
2023-07-26 12:30:34 +00:00
|
|
|
|
2023-11-15 11:37:10 +00:00
|
|
|
snmp_blank_header(h, AGENTX_RESPONSE_PDU);
|
|
|
|
snmp_session(p, h);
|
2023-07-26 12:30:34 +00:00
|
|
|
|
2023-10-19 14:08:13 +00:00
|
|
|
/* protocol doesn't care about subagent upTime */
|
|
|
|
STORE_U32(r->uptime, 0);
|
|
|
|
STORE_U16(r->error, AGENTX_RES_NO_ERROR);
|
|
|
|
STORE_U16(r->index, 0);
|
2023-07-26 12:30:34 +00:00
|
|
|
|
2023-10-19 14:08:13 +00:00
|
|
|
ADVANCE(c->buffer, c->size, sizeof(struct agentx_response));
|
|
|
|
return r;
|
2023-07-26 12:30:34 +00:00
|
|
|
}
|