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

SNMP: tmp

This commit is contained in:
Vojtech Vilimek 2024-07-24 13:38:36 +02:00
parent bdb0b7cad4
commit a34fea55ec
5 changed files with 75 additions and 56 deletions

View File

@ -26,9 +26,6 @@
/* hash table only store ip4 addresses */
#define SNMP_HASH_LESS(ip1, ip2) SNMP_HASH_LESS4(ip1,ip2)
// delete me
#define SNMP_MANAGE_TBUF(...) (void)0
#define DECLARE_BGP4(addr, proto, conn, stats, config) \
ip4_addr addr; \
const struct bgp_proto UNUSED *proto; \
@ -63,6 +60,7 @@ snmp_bgp_last_error(const struct bgp_proto *bgp, char err[2])
static void
snmp_bgp_reg_ok(struct snmp_proto *p, const struct agentx_response *res, struct snmp_registration *reg)
{
/* TODO(contexts): add meaningful action */
const struct oid * const oid = reg->oid;
(void)oid;
(void)p;
@ -72,6 +70,7 @@ snmp_bgp_reg_ok(struct snmp_proto *p, const struct agentx_response *res, struct
static void
snmp_bgp_reg_failed(struct snmp_proto *p, const struct agentx_response *res, struct snmp_registration *reg)
{
/* TODO(contexts): add meaningful action */
const struct oid * const oid = reg->oid;
(void) res;
(void)oid;
@ -379,6 +378,13 @@ populate_bgp4(struct snmp_pdu *c, ip4_addr *addr, const struct bgp_proto **proto
return SNMP_SEARCH_OK;
}
/*
*
* MIB tree fill hooks
*
*/
static enum snmp_search_res
fill_bgp_version(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c)
{
@ -785,7 +791,11 @@ fill_local_id(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c)
}
/*
* bgp4_next_peer
* bgp4_next_peer - find next BGP peer with IPv4 address
* @state: MIB tree walk state
* @c: SNMP PDU context data
*
* Update TX-buffer VarBind name to next peer address.
*/
static int
bgp4_next_peer(struct mib_walk_state *state, struct snmp_pdu *c)
@ -821,8 +831,7 @@ bgp4_next_peer(struct mib_walk_state *state, struct snmp_pdu *c)
ASSUME(oid->n_subid == 9);
/* full path BGP4-MIB::bgpPeerEntry.x: .1.3.6.1.2.1.15.3.1.x
* index offset = ARRAY_SIZE(snmp_internet) + 1 <prefix> + 4 + 1 <identifier x> */
/* Stack has one more node for empty prefix (tree root) */
ASSUME(state->stack_pos > 10);
oid->ids[4] = state->stack[10]->empty.id;
@ -871,8 +880,8 @@ snmp_bgp4_start(struct snmp_proto *p)
struct snmp_config *cf = SKIP_BACK(struct snmp_config, cf, p->p.cf);
/* Create binding to BGP protocols */
/* Create binding to BGP protocols */
struct snmp_bond *b;
WALK_LIST(b, cf->bgp_entries)
{

View File

@ -151,10 +151,10 @@ void agentx_get_mib_init(pool *p)
/*
* agentx_get_mib - classify an OID based on MIB prefix
*
*/
enum agentx_mibs agentx_get_mib(const struct oid *o)
{
/* TODO: move me into MIB tree as hooks/MIB module root */
enum agentx_mibs mib = AGENTX_MIB_UNKNOWN;
for (uint i = 0; i < AGENTX_MIB_COUNT + 1; i++)
{
@ -214,19 +214,6 @@ snmp_set_state(struct snmp_proto *p, enum snmp_proto_state state)
TRACE(D_EVENTS, "SNMP changing state to %u", state);
if (state == SNMP_DOWN && (last == SNMP_REGISTER || last == SNMP_CONN))
{
/* We have a connection established (at least send out agentx-Open-PDU) */
state = SNMP_STOP;
}
/* else - We did not send any packet, we perform protocol cleanup only. */
if (last == SNMP_RESET)
{
rfree(p->sock);
p->sock = NULL;
}
p->state = state;
switch (state)
@ -321,14 +308,17 @@ snmp_set_state(struct snmp_proto *p, enum snmp_proto_state state)
DBG("snmp -> SNMP_STOP\n");
ASSUME(last == SNMP_REGISTER || last == SNMP_CONN);
snmp_stop_subagent(p);
// FIXME: special treatment for SNMP_OPEN last state?
p->sock->rx_hook = snmp_rx_skip;
p->sock->tx_hook = snmp_tx_skip;
p->startup_timer->hook = snmp_stop_timeout;
tm_start(p->startup_timer, p->timeout);
return PS_STOP;
case SNMP_DOWN:
DBG("snmp -> SNMP_DOWN\n");
ASSERT(last == SNMP_STOP || last == SNMP_RESET);
snmp_cleanup(p);
// FIXME: handle the state in which we call proto_notify_state and
// immediately return PS_DOWN from snmp_shutdown()
@ -338,7 +328,8 @@ snmp_set_state(struct snmp_proto *p, enum snmp_proto_state state)
DBG("snmp -> SNMP_RESET\n");
ASSUME(last == SNMP_REGISTER || last == SNMP_CONN);
ASSUME(p->sock);
snmp_stop_subagent(p);
tm_stop(p->ping_timer);
// FIXME: special treatment for SNMP_OPEN last state?
p->sock->rx_hook = snmp_rx_skip;
p->sock->tx_hook = snmp_tx_skip;
return PS_STOP;
@ -423,20 +414,35 @@ snmp_connected(sock *sk)
}
/*
* snmp_reset - end the communication on AgentX session
* @p - SNMP protocol instance
* snmp_reset - reset AgentX session
* @p: SNMP protocol instance
*
* End the communication on AgentX session by downing the whole procotol. This
* causes socket closure that implies AgentX session disconnection.
* This function is internal and shouldn't be used outside the SNMP module.
* We wait until the last PDU written into the socket is send while ignoring all
* incomming PDUs. Then we hard reset the connection by socket closure. The
* protocol instance is automatically restarted by nest.
*/
void
snmp_reset(struct snmp_proto *p)
{
tm_stop(p->ping_timer);
proto_notify_state(&p->p, snmp_set_state(p, SNMP_DOWN));
proto_notify_state(&p->p, snmp_set_state(p, SNMP_RESET));
}
/*
* snmp_stop - close AgentX session
* @p: SNMP protocol instance
*
* We write agentx-Close-PDU into the socket, wait until all written PDUs are
* send and then close the socket. The protocol instance is automatically
* restarted by nest.
*/
void
snmp_stop(struct snmp_proto *p)
{
proto_notify_state(&p->p, snmp_set_state(p, SNMP_STOP));
}
/*
* snmp_sock_err - handle errors on socket by reopenning the socket
* @sk - socket owned by SNMP protocol instance

View File

@ -171,6 +171,7 @@ void snmp_reconnect(timer *tm);
int snmp_set_state(struct snmp_proto *p, enum snmp_proto_state state);
void snmp_reset(struct snmp_proto *p);
void snmp_stop(struct snmp_proto *p);
extern const char agentx_master_addr[sizeof(AGENTX_MASTER_ADDR)];

View File

@ -20,9 +20,6 @@
*/
/**
*
*
*
*
* Handling of malformed packet:
*
@ -91,7 +88,7 @@ snmp_header(struct agentx_header *h, enum agentx_pdu_types type, u8 flags)
}
/*
* snmp_blank_header - create header with no flags except default
* snmp_blank_header - create header with no flags except byte order
* @h: pointer to created header in TX-buffer
* @type: create PDU type
*
@ -239,7 +236,7 @@ snmp_notify_pdu(struct snmp_proto *p, struct oid *oid, void *data, uint size, in
if (snmp_tbuf_reserve(&c, sz))
snmp_log("agentx-Notify-PDU small buffer");
struct agentx_header *h = (void *) c.buffer;
struct agentx_header *h = (struct agentx_header *) c.buffer;
ADVANCE(c.buffer, c.size, AGENTX_HEADER_SIZE);
snmp_blank_header(h, AGENTX_NOTIFY_PDU);
p->packet_id++; /* New packet id */
@ -351,7 +348,7 @@ un_register_pdu(struct snmp_proto *p, struct oid *oid, u32 bound, uint index, en
STORE_U8(ur->reserved, 0);
ADVANCE(c.buffer, c.size, sizeof(struct agentx_un_register_hdr));
snmp_put_oid(c.buffer, oid);
(void) snmp_put_oid(c.buffer, oid);
ADVANCE(c.buffer, c.size, snmp_oid_size(oid));
/* place upper-bound if needed */
@ -522,7 +519,7 @@ parse_test_set_pdu(struct snmp_proto *p, byte * const pkt_start)
if (c.error != AGENTX_RES_NO_ERROR)
{
response_err_ind(p, res, c.error, c.index + 1);
snmp_reset(p); // error
snmp_reset(p);
}
else if (all_possible)
{
@ -676,24 +673,24 @@ space_for_response(const sock *sk)
static uint
parse_pkt(struct snmp_proto *p, byte *pkt, uint size)
{
snmp_log("parse_pkt %t", current_time());
/* TX-buffer free space */
if (size < AGENTX_HEADER_SIZE)
return 0;
struct agentx_header *h = (void *) pkt;
struct agentx_header *h = (struct agentx_header *) pkt;
if (h->flags & AGENTX_NETWORK_BYTE_ORDER)
{
TRACE(D_PACKETS, "SNMP received PDU with unexpected byte order");
snmp_simple_response(p, AGENTX_RES_GEN_ERROR, 0);
snmp_reset(p);
return 0;
}
uint pkt_size = LOAD_U32(h->payload);
u32 pkt_size = LOAD_U32(h->payload);
/* RX side checks - too big packet */
if (pkt_size > SNMP_PKT_SIZE_MAX)
{
TRACE(D_PACKETS, "SNMP received PDU is too long");
snmp_simple_response(p, AGENTX_RES_GEN_ERROR, 0);
snmp_reset(p);
return 0; /* no bytes parsed */
@ -703,7 +700,8 @@ parse_pkt(struct snmp_proto *p, byte *pkt, uint size)
if (size < pkt_size + AGENTX_HEADER_SIZE)
return 0; /* no bytes parsed */
/* We need to see the responses for PDU such as
/*
* We need to see the responses for PDU such as
* agentx-Open-PDU, agentx-Register-PDU, ...
* even when we are outside the SNMP_CONNECTED state
*/
@ -726,7 +724,6 @@ parse_pkt(struct snmp_proto *p, byte *pkt, uint size)
p->session_id = copy.session_id;
p->transaction_id = copy.transaction_id;
p->packet_id = copy.packet_id;
snmp_log("restoring packet_id %u from temporal state", p->packet_id);
/*
* After unexpected state, we simply reset the session
@ -740,11 +737,12 @@ parse_pkt(struct snmp_proto *p, byte *pkt, uint size)
{
TRACE(D_PACKETS, "SNMP received PDU with non-default context");
snmp_simple_response(p, AGENTX_RES_UNSUPPORTED_CONTEXT, 0);
return pkt_size + AGENTX_HEADER_SIZE;
snmp_reset(p);
return 0;
}
refresh_ids(p, h);
switch (h->type)
switch (LOAD_U8(h->type))
{
case AGENTX_GET_PDU:
case AGENTX_GET_NEXT_PDU:
@ -768,8 +766,8 @@ parse_pkt(struct snmp_proto *p, byte *pkt, uint size)
default:
/* We reset the connection for malformed packet (Unknown packet type) */
TRACE(D_PACKETS, "SNMP received unknown packet with type %u", h->type);
snmp_set_state(p, SNMP_RESET);
TRACE(D_PACKETS, "SNMP received unknown packet with type %u", LOAD_U8(h->type));
snmp_reset(p);
return 0;
}
}
@ -821,8 +819,8 @@ parse_response(struct snmp_proto *p, byte *res)
case AGENTX_RES_PARSE_ERROR:
case AGENTX_RES_PROCESSING_ERR:
default:
DBG("SNMP agentx-Response-PDU with unexpected error %u", r->error);
snmp_set_state(p, SNMP_DOWN);
TRACE(D_PACKETS, "SNMP agentx-Response-PDU with unexepected error %u", r->error);
snmp_stop(p);
break;
}
@ -924,7 +922,7 @@ snmp_vb_to_tx(struct snmp_pdu *c, const struct oid *oid)
snmp_log("SNMP vb_to_tx small buffer");
ASSERT(c->size >= vb_hdr_size);
struct agentx_varbind *vb = (void *) c->buffer;
struct agentx_varbind *vb = (struct agentx_varbind *) c->buffer;
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);
@ -973,12 +971,12 @@ update_packet_size(struct agentx_header *start, byte *end)
static inline void
response_err_ind(struct snmp_proto *p, struct agentx_response *res, enum agentx_response_errs err, u16 ind)
{
STORE_U32(res->error, (u16) err);
STORE_U16(res->error, (u16) err);
// 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);
STORE_U32(res->index, ind);
STORE_U16(res->index, ind);
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);
@ -986,13 +984,13 @@ response_err_ind(struct snmp_proto *p, struct agentx_response *res, enum agentx_
else if (err == AGENTX_RES_GEN_ERROR)
{
TRACE(D_PACKETS, "Last PDU resulted in error %u genErr", err);
STORE_U32(res->index, 0);
STORE_U16(res->index, 0);
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
STORE_U32(res->index, 0);
STORE_U16(res->index, 0);
}
static inline uint
@ -1263,8 +1261,7 @@ snmp_stop_subagent(struct snmp_proto *p)
int
snmp_rx(sock *sk, uint size)
{
snmp_log("snmp_rx with size %u", size);
struct snmp_proto *p = sk->data;
struct snmp_proto *p = (struct snmp_proto *) sk->data;
byte *pkt_start = sk->rbuf;
byte *end = pkt_start + size;

View File

@ -148,7 +148,6 @@ enum agentx_flags {
#define COPY_STR(proto, buf, str, length) ({ \
length = LOAD_PTR(buf); \
/*log(L_INFO "LOAD_STR(), %p %u", proto->pool, length + 1); */ \
str = mb_alloc(proto->pool, length + 1); \
memcpy(str, buf+4, length); \
str[length] = '\0'; /* set term. char */ \
@ -235,6 +234,13 @@ struct agentx_response {
STATIC_ASSERT(4 + 2 + 2 + AGENTX_HEADER_SIZE == sizeof(struct agentx_response));
struct agentx_open_pdu {
struct agentx_header h;
u8 timeout;
u8 reserved1; /* reserved u24 */
u16 reserved2; /* whole u24 is always zero filled */
};
struct agentx_close_pdu {
struct agentx_header h;
u8 reason;