From 661a4277bbcc4aa851f2607998967b2ce23717f9 Mon Sep 17 00:00:00 2001 From: Vojtech Vilimek Date: Wed, 25 Oct 2023 16:44:08 +0200 Subject: [PATCH] SNMP: Refactoring --- proto/snmp/bgp_mib.c | 282 ++++++++++++++++++++-------------------- proto/snmp/snmp_utils.c | 26 ---- proto/snmp/snmp_utils.h | 3 +- proto/snmp/subagent.c | 26 ++++ 4 files changed, 169 insertions(+), 168 deletions(-) diff --git a/proto/snmp/bgp_mib.c b/proto/snmp/bgp_mib.c index c02400fc..f3e9b347 100644 --- a/proto/snmp/bgp_mib.c +++ b/proto/snmp/bgp_mib.c @@ -53,6 +53,148 @@ static const char * const debug_bgp_states[] UNUSED = { [BGP_INTERNAL_NO_VALUE] = "BGP_INTERNAL_NO_VALUE", }; +static u8 +bgp_get_candidate(u32 field) +{ + const u8 translation_table[] = { + [SNMP_BGP_PEER_IDENTIFIER] = BGP_INTERNAL_PEER_IDENTIFIER, + [SNMP_BGP_STATE] = BGP_INTERNAL_STATE, + [SNMP_BGP_ADMIN_STATUS] = BGP_INTERNAL_ADMIN_STATUS, + [SNMP_BGP_NEGOTIATED_VERSION] = BGP_INTERNAL_NEGOTIATED_VERSION, + [SNMP_BGP_LOCAL_ADDR] = BGP_INTERNAL_LOCAL_ADDR, + [SNMP_BGP_LOCAL_PORT] = BGP_INTERNAL_LOCAL_PORT, + [SNMP_BGP_REMOTE_ADDR] = BGP_INTERNAL_REMOTE_ADDR, + [SNMP_BGP_REMOTE_PORT] = BGP_INTERNAL_REMOTE_PORT, + [SNMP_BGP_REMOTE_AS] = BGP_INTERNAL_REMOTE_AS, + [SNMP_BGP_RX_UPDATES] = BGP_INTERNAL_RX_UPDATES, + [SNMP_BGP_TX_UPDATES] = BGP_INTERNAL_TX_UPDATES, + [SNMP_BGP_RX_MESSAGES] = BGP_INTERNAL_RX_MESSAGES, + [SNMP_BGP_TX_MESSAGES] = BGP_INTERNAL_TX_MESSAGES, + [SNMP_BGP_LAST_ERROR] = BGP_INTERNAL_LAST_ERROR, + [SNMP_BGP_FSM_TRANSITIONS] = BGP_INTERNAL_FSM_TRANSITIONS, + [SNMP_BGP_FSM_ESTABLISHED_TIME] = BGP_INTERNAL_FSM_ESTABLISHED_TIME, + [SNMP_BGP_RETRY_INTERVAL] = BGP_INTERNAL_RETRY_INTERVAL, + [SNMP_BGP_HOLD_TIME] = BGP_INTERNAL_HOLD_TIME, + [SNMP_BGP_KEEPALIVE] = BGP_INTERNAL_KEEPALIVE, + [SNMP_BGP_HOLD_TIME_CONFIGURED] = BGP_INTERNAL_HOLD_TIME_CONFIGURED, + [SNMP_BGP_KEEPALIVE_CONFIGURED] = BGP_INTERNAL_KEEPALIVE_CONFIGURED, + [SNMP_BGP_ORIGINATION_INTERVAL] = BGP_INTERNAL_ORIGINATION_INTERVAL, + [SNMP_BGP_MIN_ROUTE_ADVERTISEMENT] = BGP_INTERNAL_MIN_ROUTE_ADVERTISEMENT, + [SNMP_BGP_IN_UPDATE_ELAPSED_TIME] = BGP_INTERNAL_IN_UPDATE_ELAPSED_TIME, + }; + + /* + * First value is in secord cell of array translation_table, as the + * SNMP_BPG_IDENTIFIER == 1 + */ + if (field > 0 && field <= ARRAY_SIZE(translation_table)- 1) + return translation_table[field]; + if (field == 0) + return BGP_INTERNAL_PEER_ENTRY; + else + return BGP_INTERNAL_PEER_TABLE_END; +} + +/** + * snmp_bgp_state - linearize oid from BGP4-MIB + * @oid: prefixed object identifier from BGP4-MIB::bgp subtree + * + * Returns linearized state for Get-PDU, GetNext-PDU and GetBulk-PDU packets. + */ +static u8 +snmp_bgp_state(const struct oid *oid) +{ + /* + * Ids of Object Identifier that are already checked: + * internet oid.prefix + * v...... v + * (*oid): .1.3.6.1.2.1.15 + * -> BGP4-MIB::bgp (root) + */ + + if (snmp_is_oid_empty(oid)) + return BGP_INTERNAL_END; + + u8 state = BGP_INTERNAL_NO_VALUE; + + u8 candidate; + switch (oid->n_subid) + { + default: + if (oid->n_subid < 2) + { + state = BGP_INTERNAL_INVALID; + break; + } + + /* fall through */ + + /* + * Between ids[5] and ids[8] (n_subid == 9) should be IP address. + * Validity is checked later in execution because + * this field also could mean a query boundry (upper or lower). + */ + case 9: + case 8: + case 7: + case 6: + case 5: + state = bgp_get_candidate(oid->ids[4]); + + /* fall through */ + + case 4: + if (oid->ids[3] == SNMP_BGP_PEER_ENTRY) + state = (state == BGP_INTERNAL_NO_VALUE) ? + BGP_INTERNAL_PEER_ENTRY : state; + else + state = BGP_INTERNAL_NO_VALUE; + + /* fall through */ + + case 3: + /* u8 candidate; */ + switch (oid->ids[2]) + { + + case SNMP_BGP_VERSION: + state = BGP_INTERNAL_VERSION; + break; + case SNMP_BGP_LOCAL_AS: + state = BGP_INTERNAL_LOCAL_AS; + break; + case SNMP_BGP_PEER_TABLE: + /* We use candidate to avoid overriding more specific state */ + candidate = BGP_INTERNAL_PEER_TABLE; + break; + case SNMP_BGP_IDENTIFIER: + state = BGP_INTERNAL_IDENTIFIER; + break; + + default: /* test fails */ + /* We force state invalidation */ + if (oid->ids[2] < SNMP_BGP_VERSION) + { + state = BGP_INTERNAL_NO_VALUE; + candidate = BGP_INTERNAL_NO_VALUE; + } + else /* oid->ids[2] > SNMP_BGP_PEER_TABLE */ + state = BGP_INTERNAL_END; + } + state = (state == BGP_INTERNAL_NO_VALUE) ? + candidate : state; + + /* fall through */ + + case 2: /* We found bare BGP4-MIB::bgp ObjectId */ + if (state == BGP_INTERNAL_NO_VALUE || + state == BGP_INTERNAL_INVALID) + state = BGP_INTERNAL_BGP; + } + + return state; +} + static void snmp_bgp_notify_common(struct snmp_proto *p, uint type, ip4_addr ip4, char last_error[], uint state_val) { @@ -194,47 +336,6 @@ snmp_bgp_valid_ip4(struct oid *o) return snmp_valid_ip4_index(o, 5); } -static u8 -bgp_get_candidate(u32 field) -{ - const u8 translation_table[] = { - [SNMP_BGP_PEER_IDENTIFIER] = BGP_INTERNAL_PEER_IDENTIFIER, - [SNMP_BGP_STATE] = BGP_INTERNAL_STATE, - [SNMP_BGP_ADMIN_STATUS] = BGP_INTERNAL_ADMIN_STATUS, - [SNMP_BGP_NEGOTIATED_VERSION] = BGP_INTERNAL_NEGOTIATED_VERSION, - [SNMP_BGP_LOCAL_ADDR] = BGP_INTERNAL_LOCAL_ADDR, - [SNMP_BGP_LOCAL_PORT] = BGP_INTERNAL_LOCAL_PORT, - [SNMP_BGP_REMOTE_ADDR] = BGP_INTERNAL_REMOTE_ADDR, - [SNMP_BGP_REMOTE_PORT] = BGP_INTERNAL_REMOTE_PORT, - [SNMP_BGP_REMOTE_AS] = BGP_INTERNAL_REMOTE_AS, - [SNMP_BGP_RX_UPDATES] = BGP_INTERNAL_RX_UPDATES, - [SNMP_BGP_TX_UPDATES] = BGP_INTERNAL_TX_UPDATES, - [SNMP_BGP_RX_MESSAGES] = BGP_INTERNAL_RX_MESSAGES, - [SNMP_BGP_TX_MESSAGES] = BGP_INTERNAL_TX_MESSAGES, - [SNMP_BGP_LAST_ERROR] = BGP_INTERNAL_LAST_ERROR, - [SNMP_BGP_FSM_TRANSITIONS] = BGP_INTERNAL_FSM_TRANSITIONS, - [SNMP_BGP_FSM_ESTABLISHED_TIME] = BGP_INTERNAL_FSM_ESTABLISHED_TIME, - [SNMP_BGP_RETRY_INTERVAL] = BGP_INTERNAL_RETRY_INTERVAL, - [SNMP_BGP_HOLD_TIME] = BGP_INTERNAL_HOLD_TIME, - [SNMP_BGP_KEEPALIVE] = BGP_INTERNAL_KEEPALIVE, - [SNMP_BGP_HOLD_TIME_CONFIGURED] = BGP_INTERNAL_HOLD_TIME_CONFIGURED, - [SNMP_BGP_KEEPALIVE_CONFIGURED] = BGP_INTERNAL_KEEPALIVE_CONFIGURED, - [SNMP_BGP_ORIGINATION_INTERVAL] = BGP_INTERNAL_ORIGINATION_INTERVAL, - [SNMP_BGP_MIN_ROUTE_ADVERTISEMENT] = BGP_INTERNAL_MIN_ROUTE_ADVERTISEMENT, - [SNMP_BGP_IN_UPDATE_ELAPSED_TIME] = BGP_INTERNAL_IN_UPDATE_ELAPSED_TIME, - }; - - /* - * First value is in secord cell of array translation_table, as the - * SNMP_BPG_IDENTIFIER == 1 - */ - if (field > 0 && field <= sizeof(translation_table) / sizeof(translation_table[0]) - 1) - return translation_table[field]; - if (field == 0) - return BGP_INTERNAL_PEER_ENTRY; - else - return BGP_INTERNAL_PEER_TABLE_END; -} static inline struct ip4_addr ip4_from_oid(const struct oid *o) @@ -315,105 +416,6 @@ print_bgp_record_all(struct snmp_proto *p) } -/** - * snmp_bgp_state - linearize oid from BGP4-MIB - * @oid: prefixed object identifier from BGP4-MIB::bgp subtree - * - * Returns linearized state for Get-PDU, GetNext-PDU and GetBulk-PDU packets. - */ -static u8 -snmp_bgp_state(const struct oid *oid) -{ - /* - * Ids of Object Identifier that are already checked: - * internet oid.prefix - * v...... v - * (*oid): .1.3.6.1.2.1.15 - * -> BGP4-MIB::bgp (root) - */ - - if (snmp_is_oid_empty(oid)) - return BGP_INTERNAL_END; - - u8 state = BGP_INTERNAL_NO_VALUE; - - u8 candidate; - switch (oid->n_subid) - { - default: - if (oid->n_subid < 2) - { - state = BGP_INTERNAL_INVALID; - break; - } - - /* fall through */ - - /* - * Between ids[5] and ids[8] (n_subid == 9) should be IP address. - * Validity is checked later in execution because - * this field also could mean a query boundry (upper or lower). - */ - case 9: - case 8: - case 7: - case 6: - case 5: - state = bgp_get_candidate(oid->ids[4]); - - /* fall through */ - - case 4: - if (oid->ids[3] == SNMP_BGP_PEER_ENTRY) - state = (state == BGP_INTERNAL_NO_VALUE) ? - BGP_INTERNAL_PEER_ENTRY : state; - else - state = BGP_INTERNAL_NO_VALUE; - - /* fall through */ - - case 3: - /* u8 candidate; */ - switch (oid->ids[2]) - { - - case SNMP_BGP_VERSION: - state = BGP_INTERNAL_VERSION; - break; - case SNMP_BGP_LOCAL_AS: - state = BGP_INTERNAL_LOCAL_AS; - break; - case SNMP_BGP_PEER_TABLE: - /* We use candidate to avoid overriding more specific state */ - candidate = BGP_INTERNAL_PEER_TABLE; - break; - case SNMP_BGP_IDENTIFIER: - state = BGP_INTERNAL_IDENTIFIER; - break; - - default: /* test fails */ - /* We force state invalidation */ - if (oid->ids[2] < SNMP_BGP_VERSION) - { - state = BGP_INTERNAL_NO_VALUE; - candidate = BGP_INTERNAL_NO_VALUE; - } - else /* oid->ids[2] > SNMP_BGP_PEER_TABLE */ - state = BGP_INTERNAL_END; - } - state = (state == BGP_INTERNAL_NO_VALUE) ? - candidate : state; - - /* fall through */ - - case 2: /* We found bare BGP4-MIB::bgp ObjectId */ - if (state == BGP_INTERNAL_NO_VALUE || - state == BGP_INTERNAL_INVALID) - state = BGP_INTERNAL_BGP; - } - - return state; -} static inline int is_dynamic(u8 state) diff --git a/proto/snmp/snmp_utils.c b/proto/snmp/snmp_utils.c index 7a13fe38..516cc92d 100644 --- a/proto/snmp/snmp_utils.c +++ b/proto/snmp/snmp_utils.c @@ -429,32 +429,6 @@ snmp_register_same(struct snmp_register *r, struct agentx_header *h, u8 class) (r->packet_id == h->packet_id); } -void -snmp_register_ack(struct snmp_proto *p, struct agentx_header *h, u8 class) -{ - struct snmp_register *reg; - WALK_LIST(reg, p->register_queue) - { - // TODO add support for more mib trees (other than BGP) - if (snmp_register_same(reg, h, class)) - { - struct snmp_registered_oid *ro = \ - mb_alloc(p->p.pool, sizeof(struct snmp_registered_oid)); - - ro->n.prev = ro->n.next = NULL; - - ro->oid = reg->oid; - - rem_node(®->n); - mb_free(reg); - p->register_to_ack--; - - add_tail(&p->bgp_registered, &ro->n); - - return; - } - } -} void UNUSED snmp_dump_packet(byte UNUSED *pkt, uint size) diff --git a/proto/snmp/snmp_utils.h b/proto/snmp/snmp_utils.h index 733cbabe..0cad57e9 100644 --- a/proto/snmp/snmp_utils.h +++ b/proto/snmp/snmp_utils.h @@ -45,8 +45,7 @@ void snmp_oid_dump(const struct oid *oid); //struct oid *snmp_prefixize(struct snmp_proto *p, struct oid *o, int byte_ord); struct snmp_register *snmp_register_create(struct snmp_proto *p, u8 mib_class); - -void snmp_register_ack(struct snmp_proto *p, struct agentx_header *h, u8 class); +int snmp_register_same(struct snmp_register *r, struct agentx_header *h, u8 class); byte *snmp_varbind_int(struct agentx_varbind *vb, uint size, u32 val); byte *snmp_varbind_counter32(struct agentx_varbind *vb, uint size, u32 val); diff --git a/proto/snmp/subagent.c b/proto/snmp/subagent.c index 84a6b1c1..28283add 100644 --- a/proto/snmp/subagent.c +++ b/proto/snmp/subagent.c @@ -77,6 +77,32 @@ static const char * const snmp_pkt_type[] UNUSED = { [AGENTX_RESPONSE_PDU] = "Response-PDU", }; +void +snmp_register_ack(struct snmp_proto *p, struct agentx_header *h, u8 class) +{ + struct snmp_register *reg; + WALK_LIST(reg, p->register_queue) + { + // TODO add support for more mib trees (other than BGP) + if (snmp_register_same(reg, h, class)) + { + struct snmp_registered_oid *ro = \ + mb_alloc(p->p.pool, sizeof(struct snmp_registered_oid)); + + ro->n.prev = ro->n.next = NULL; + + ro->oid = reg->oid; + + rem_node(®->n); + mb_free(reg); + p->register_to_ack--; + + add_tail(&p->bgp_registered, &ro->n); + return; + } + } +} + static int snmp_rx_skip(sock UNUSED *sk, uint UNUSED size) {