[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)
{
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)
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);
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
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 };
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;
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);
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__)