0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2025-01-03 07:31:54 +00:00

SNMP: BGP4-MIB notifications

This commit is contained in:
Vojtech Vilimek 2023-09-04 13:53:45 +02:00
parent c765faef17
commit 8a1f2dba66
4 changed files with 99 additions and 66 deletions

View File

@ -49,6 +49,73 @@ static const char * const debug_bgp_states[] UNUSED = {
[BGP_INTERNAL_NO_VALUE] = "BGP_INTERNAL_NO_VALUE",
};
static void
snmp_bgp_notify_common(struct snmp_proto *p, uint type, ip4_addr ip4, char last_error[], uint state_val)
{
// TODO remove heap allocation, put the data on stack
#define SNMP_OID_SIZE_FROM_LEN(x) (sizeof(struct oid) + (x) * sizeof(u32))
/* trap OID bgpEstablishedNotification (.1.3.6.1.2.1.0.1) */
struct oid *head = mb_alloc(p->p.pool, SNMP_OID_SIZE_FROM_LEN(3));
head->n_subid = 3;
head->prefix = 2;
head->include = head->pad = 0;
u32 trap_ids[] = { 1, 0, type };
for (uint i = 0; i < head->n_subid; i++)
head->ids[i] = trap_ids[i];
/* OIDs, VB type headers, octet string, ip4 address, integer */
uint sz = 3 * SNMP_OID_SIZE_FROM_LEN(9) + 3 * 4 + 8 + 8 + 4;
/* Paylaod OIDs */
void *data = mb_alloc(p->p.pool, sz);
struct agentx_varbind *addr_vb = data;
/* +4 for varbind header, +8 for octet string */
struct agentx_varbind *error_vb = data + SNMP_OID_SIZE_FROM_LEN(9) + 4 + 8;
struct agentx_varbind *state_vb = (void *) error_vb + SNMP_OID_SIZE_FROM_LEN(9) + 4 + 8;
addr_vb->pad = error_vb->pad = state_vb->pad = 0;
struct oid *addr = &addr_vb->name;
struct oid *error = &error_vb->name;
struct oid *state = &state_vb->name;
addr->n_subid = error->n_subid = state->n_subid = 9;
addr->prefix = error->prefix = state->prefix = 2;
addr->include = error->include = state->include = 0;
addr->pad = error->pad = state->pad = 0;
u32 oid_ids[] = {
SNMP_MIB_2, SNMP_BGP4_MIB, SNMP_BGP_PEER_TABLE, SNMP_BGP_PEER_ENTRY
};
for (uint i = 0; i < sizeof(oid_ids) / sizeof(oid_ids[0]); i++)
addr->ids[i] = error->ids[i] = state->ids[i] = oid_ids[i];
addr->ids[4] = SNMP_BGP_REMOTE_ADDR;
error->ids[4] = SNMP_BGP_LAST_ERROR;
state->ids[4] = SNMP_BGP_STATE;
for (uint i = 0; i < 4; i++)
addr->ids[5 + i] = error->ids[5 + i] = state->ids[5 + i] \
= (ip4_to_u32(ip4) >> (8 * (3-i))) & 0xFF;
snmp_varbind_ip4(addr_vb, 100, ip4);
snmp_varbind_nstr(error_vb, 100, last_error, 2);
snmp_varbind_int(state_vb, 100, state_val);
snmp_notify_pdu(p, head, data, sz, 0);
mb_free(head);
mb_free(data);
#undef SNMP_OID_SIZE_FROM_LEN
}
static inline uint
snmp_bgp_fsm_state(struct bgp_proto *bgp_proto)
{
@ -68,6 +135,29 @@ snmp_bgp_fsm_state(struct bgp_proto *bgp_proto)
return MAX(bgp_in->state, bgp_out->state);
}
static void
snmp_bgp_notify_wrapper(struct snmp_proto *p, struct bgp_proto *bgp, uint type)
{
// possibly dangerous
ip4_addr ip4 = ipa_to_ip4(bgp->remote_ip);
char last_error[2] = SNMP_BGP_LAST_ERROR(bgp);
uint state_val = snmp_bgp_fsm_state(bgp);
snmp_bgp_notify_common(p, type, ip4, last_error, state_val);
}
void
snmp_bgp_notify_established(struct snmp_proto *p, struct bgp_proto *bgp)
{
/* .1.3.6.1.2.15.0.>1< i.e. BGP4-MIB::bgpEstablishedNotification */
snmp_bgp_notify_wrapper(p, bgp, 1);
}
void
snmp_bgp_notify_backward_trans(struct snmp_proto *p, struct bgp_proto *bgp)
{
/* .1.3.6.1.2.15.0.>2< i.e. BGP4-MIB::bgpBackwardTransNotification */
snmp_bgp_notify_wrapper(p, bgp, 2);
}
void
snmp_bgp_register(struct snmp_proto *p)
@ -894,11 +984,8 @@ bgp_fill_dynamic(struct snmp_proto UNUSED *p, struct agentx_varbind *vb,
return ((byte *) vb) + snmp_varbind_header_size(vb);
}
struct bgp_conn *bgp_conn = bgp_proto->conn;
struct bgp_conn *bgp_in = &bgp_proto->incoming_conn;
struct bgp_conn *bgp_out = &bgp_proto->outgoing_conn;
struct bgp_stats *bgp_stats = &bgp_proto->stats;
const struct bgp_conn *bgp_conn = bgp_proto->conn;
const struct bgp_stats *bgp_stats = &bgp_proto->stats;
const struct bgp_config *bgp_conf = bgp_proto->cf;
uint bgp_state = snmp_bgp_fsm_state(bgp_proto);

View File

@ -47,6 +47,9 @@ struct oid *snmp_bgp_search(struct snmp_proto *p, struct oid *o_start, struct oi
enum snmp_search_res snmp_bgp_search2(struct snmp_proto *p, struct oid **searched, const struct oid *o_end, uint contid);
void snmp_bgp_fill(struct snmp_proto *p, struct agentx_varbind *vb, struct snmp_pdu_context *c);
void snmp_bgp_notify_established(struct snmp_proto *p, struct bgp_proto *bgp);
void snmp_bgp_notify_backward_trans(struct snmp_proto *p, struct bgp_proto *bgp);
#define SNMP_BGP_VERSION 1
#define SNMP_BGP_LOCAL_AS 2
#define SNMP_BGP_PEER_TABLE 3

View File

@ -36,7 +36,6 @@ static struct agentx_response *prepare_response(struct snmp_proto *p, struct snm
static void response_err_ind(struct agentx_response *res, uint err, uint ind);
static uint update_packet_size(struct snmp_proto *p, 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_context *c, enum snmp_search_res *result);
static void notify_pdu(struct snmp_proto *p, struct oid *oid, void *opaque, uint size, int include_uptime);
u32 snmp_internet[] = { SNMP_ISO, SNMP_ORG, SNMP_DOD, SNMP_INTERNET };
@ -122,8 +121,8 @@ open_pdu(struct snmp_proto *p, struct oid *oid)
snmp_log("sk_send error");
}
static void
notify_pdu(struct snmp_proto *p, struct oid *oid, void *opaque, uint size, int include_uptime)
void
snmp_notify_pdu(struct snmp_proto *p, struct oid *oid, void *opaque, uint size, int include_uptime)
{
sock *sk = p->sock;
@ -1227,64 +1226,6 @@ snmp_rx(sock *sk, uint size)
void
snmp_ping(struct snmp_proto *p)
{
{
#define SNMP_OID_SIZE_FROM_LEN(x) (sizeof(struct oid) + (x) * sizeof(u32))
/* trap OID bgpEstablishedNotification (.1.3.6.1.2.1.0.1) */
struct oid *head = mb_alloc(p->p.pool, SNMP_OID_SIZE_FROM_LEN(3));
head->n_subid = 3;
head->prefix = 2;
head->include = head->pad = 0;
u32 trap_ids[] = { 1, 0, 1 };
for (uint i = 0; i < head->n_subid; i++)
head->ids[i] = trap_ids[i];
/* paylaod oids */
uint sz = 3 * SNMP_OID_SIZE_FROM_LEN(9) + 3 * 4 + 2 * 8 + 4 - 20;
void *data = mb_alloc(p->p.pool, sz);
struct agentx_varbind *addr_vb = data;
/* +4 for varbind header, +8 for octet string */
struct agentx_varbind *error_vb = data + SNMP_OID_SIZE_FROM_LEN(9) + 4 + 8;
struct agentx_varbind *state_vb = (void *) error_vb + SNMP_OID_SIZE_FROM_LEN(9) + 4 + 8;
#undef SNMP_OID_SIZE_FROM_LEN
addr_vb->pad = error_vb->pad = state_vb->pad = 0;
struct oid *addr = &addr_vb->name;
struct oid *error = &error_vb->name;
struct oid *state = &state_vb->name;
addr->n_subid = error->n_subid = state->n_subid = 9;
addr->prefix = error->prefix = state->prefix = 2;
addr->include = error->include = state->include = 0;
addr->pad = error->pad = state->pad = 0;
u32 oid_ids[] = {
SNMP_MIB_2, SNMP_BGP4_MIB, SNMP_BGP_PEER_TABLE, SNMP_BGP_PEER_ENTRY, 0,
10, 1, 2, 1
};
for (uint i = 0; i < addr->n_subid; i++)
addr->ids[i] = error->ids[i] = state->ids[i] = oid_ids[i];
addr->ids[4] = SNMP_BGP_REMOTE_ADDR;
error->ids[4] = SNMP_BGP_LAST_ERROR;
state->ids[4] = SNMP_BGP_STATE;
ip4_addr ip4 = ip4_build(10,1,2,1);
snmp_varbind_ip4(addr_vb, 100, ip4);
char error_str[] = { 0, 0 };
snmp_varbind_nstr(error_vb, 100, error_str, 2);
snmp_varbind_int(state_vb, 100, 6);
u32 now = current_time() TO_S;
if (now % 4 == 0)
notify_pdu(p, head, data, sz, 1);
else if (now % 2 == 0)
notify_pdu(p, head, data, sz, 0);
}
sock *sk = p->sock;
snmp_dump_packet(sk->tpos, AGENTX_HEADER_SIZE + 4);
snmp_log("snmp_ping sk->tpos 0x%p", sk->tpos);

View File

@ -322,6 +322,8 @@ void snmp_manage_tbuf(struct snmp_proto *p, struct snmp_pdu_context *c);
struct oid *snmp_prefixize(struct snmp_proto *p, const struct oid *o, int byte_ord);
u8 snmp_get_mib_class(const struct oid *oid);
void snmp_notify_pdu(struct snmp_proto *p, struct oid *oid, void *opaque, uint size, int include_uptime);
// debug wrapper
#define snmp_log(...) log(L_INFO "snmp " __VA_ARGS__)