#define POPULATE_BGP4(addr, proto, conn, stats, config) populate_bgp4(c, &(addr), &(proto), &(conn), &(stats), &(config))
static inline void ip4_to_oid(struct oid *oid, ip4_addr addr);
+static const STATIC_OID(2) bgp4_mib_oid = STATIC_OID_INITIALIZER(2, SNMP_MGMT, SNMP_MIB_2, SNMP_BGP4_MIB);
static inline void
snmp_hash_add_peer(struct snmp_proto *p, struct snmp_bgp_peer *peer)
(void *) error_vb + snmp_varbind_size_from_len(9, AGENTX_OCTET_STRING, 2);
u32 oid_ids[] = {
- SNMP_MIB_2, BGP4_MIB, BGP4_MIB_PEER_TABLE, BGP4_MIB_PEER_ENTRY
+ SNMP_MIB_2, SNMP_BGP4_MIB, BGP4_MIB_PEER_TABLE, BGP4_MIB_PEER_ENTRY
};
/*
void
snmp_bgp4_register(struct snmp_proto *p)
{
- u32 bgp_mib_prefix[] = { SNMP_MIB_2, BGP4_MIB };
+ u32 bgp_mib_prefix[] = { SNMP_MIB_2, SNMP_BGP4_MIB };
{
/* Register the whole BGP4-MIB::bgp root tree node */
struct snmp_registration *reg;
- reg = snmp_registration_create(p, BGP4_MIB);
+ reg = snmp_registration_create(p, BGP4_MIB_ID);
struct oid *oid = mb_allocz(p->pool,
snmp_oid_size_from_len(ARRAY_SIZE(bgp_mib_prefix)));
return res;
if (bgp_proto->p.disabled)
- snmp_varbind_int(c, AGENTX_ADMIN_STOP);
+ snmp_varbind_int(c, BGP4_ADMIN_STOP);
else
- snmp_varbind_int(c, AGENTX_ADMIN_START);
+ snmp_varbind_int(c, BGP4_ADMIN_START);
return SNMP_SEARCH_OK;
}
struct oid *oid = &c->sr_vb_start->name;
/* BGP4-MIB::bgpPeerIdentifier */
- STATIC_OID(9) bgp4_peer_id = {
- .n_subid = 9,
- .prefix = SNMP_MGMT,
- .include = 0,
- .reserved = 0,
- .ids = { SNMP_MIB_2, BGP4_MIB,
- BGP4_MIB_PEER_TABLE, BGP4_MIB_PEER_ENTRY, BGP4_MIB_PEER_IDENTIFIER,
- /* IP4_NONE */ 0, 0, 0, 0 }
- };
+ STATIC_OID(9) bgp4_peer_id = STATIC_OID_INITIALIZER(9, SNMP_MGMT,
+ /* ids */ SNMP_MIB_2, SNMP_BGP4_MIB,
+ BGP4_MIB_PEER_TABLE, BGP4_MIB_PEER_ENTRY, BGP4_MIB_PEER_IDENTIFIER);
ip4_addr ip4 = ip4_from_oid(oid);
int old = snmp_oid_size(oid);
int new = snmp_oid_size(peer_oid);
- if (new - old > 0 && (uint) new - old > c->size)
- {
- snmp_log("bgp4_next_peer small buffer");
- snmp_manage_tbuf(c->p, c);
- oid = &c->sr_vb_start->name; // TODO fix sr_vb_start in manage_tbuf
- }
+ if (new - old > 0 && snmp_tbuf_reserve(c, new - old))
+ oid = &c->sr_vb_start->name;
c->buffer += (new - old);
}
/*
- * snmp_bgp_start - prepare BGP4-MIB
+ * snmp_bgp4_start - prepare BGP4-MIB
* @p - SNMP protocol instance holding memory pool
*
* This function create all runtime bindings to BGP procotol structures.
void
snmp_bgp4_start(struct snmp_proto *p)
{
+ agentx_available_mibs[BGP4_MIB_ID] = (struct oid *) &bgp4_mib_oid;
+
+ snmp_log("snmp_bgp4_start setting bgp4_mib oid %u %p %p %p",
+ BGP4_MIB_ID, &agentx_available_mibs[BGP4_MIB_ID], agentx_available_mibs[BGP4_MIB_ID], &bgp4_mib_oid);
+
+
struct snmp_config *cf = SKIP_BACK(struct snmp_config, cf, p->p.cf);
/* Create binding to BGP protocols */
snmp_hash_add_peer(p, peer);
}
- const STATIC_OID(2) bgp4_mib_root = {
- .n_subid = 2,
- .prefix = SNMP_MGMT,
- .include = 0,
- .reserved = 0,
- .ids = { SNMP_MIB_2, BGP4_MIB },
- };
-
- const STATIC_OID(4) bgp4_mib_peer_entry = {
- .n_subid = 4,
- .prefix = SNMP_MGMT,
- .include = 0,
- .reserved = 0,
- .ids = { SNMP_MIB_2, BGP4_MIB, BGP4_MIB_PEER_TABLE, BGP4_MIB_PEER_ENTRY },
- };
+ const STATIC_OID(4) bgp4_mib_peer_entry = STATIC_OID_INITIALIZER(4, SNMP_MGMT,
+ /* ids */ SNMP_MIB_2, SNMP_BGP4_MIB, BGP4_MIB_PEER_TABLE, BGP4_MIB_PEER_ENTRY);
(void) mib_tree_hint(p->pool, p->mib_tree,
- (const struct oid *) &bgp4_mib_root, BGP4_MIB_IDENTIFIER);
+ (const struct oid *) &bgp4_mib_oid, BGP4_MIB_IDENTIFIER);
(void) mib_tree_hint(p->pool, p->mib_tree,
(const struct oid *) &bgp4_mib_peer_entry, BGP4_MIB_IN_UPDATE_ELAPSED_TIME);
mib_node_u *node;
struct mib_leaf *leaf;
- STATIC_OID(3) bgp4_var = {
- .n_subid = 3,
- .prefix = SNMP_MGMT,
- .include = 0,
- .reserved = 0,
- .ids = { SNMP_MIB_2, BGP4_MIB, BGP4_MIB_VERSION },
- };
+ STATIC_OID(3) bgp4_var = STATIC_OID_INITIALIZER(3, SNMP_MGMT,
+ /* ids */ SNMP_MIB_2, SNMP_BGP4_MIB, BGP4_MIB_VERSION);
struct {
u32 id;
leaf->size = leafs[i].size;
}
- STATIC_OID(5) bgp4_entry_var = {
- .n_subid = 5,
- .prefix = SNMP_MGMT,
- .include = 0,
- .reserved = 0,
- .ids = { SNMP_MIB_2, BGP4_MIB,
- BGP4_MIB_PEER_TABLE, BGP4_MIB_PEER_ENTRY, BGP4_MIB_PEER_IDENTIFIER },
- };
+ STATIC_OID(5) bgp4_entry_var = STATIC_OID_INITIALIZER(5, SNMP_MGMT,
+ /* ids */ SNMP_MIB_2, SNMP_BGP4_MIB,
+ BGP4_MIB_PEER_TABLE, BGP4_MIB_PEER_ENTRY, BGP4_MIB_PEER_IDENTIFIER);
struct {
enum snmp_search_res (*filler)(struct mib_walk_state *state, struct snmp_pdu *c);
#include "proto/bgp/bgp.h"
#include "subagent.h"
-#define BGP4_MIB 15
+/* BGP4-MIB root identifier is found in snmp.h as SNMP_BGP4_MIB */
/* peers attributes */
enum bgp4_mib_peer_entry_row {
BGP4_MIB_FSM_TRANSITIONS = 15, /* FSM established transitions */
BGP4_MIB_FSM_ESTABLISHED_TIME = 16,
BGP4_MIB_RETRY_INTERVAL = 17,
- BGP4_MIB_HOLD_TIME = 18,
- BGP4_MIB_KEEPALIVE = 19,
+ BGP4_MIB_HOLD_TIME = 18, /* in read-only mode */
+ BGP4_MIB_KEEPALIVE = 19, /* in read-only mode */
BGP4_MIB_HOLD_TIME_CONFIGURED = 20,
BGP4_MIB_KEEPALIVE_CONFIGURED = 21,
BGP4_MIB_ORIGINATION_INTERVAL = 22, /* UNSUPPORTED - 0 */
} PACKED;
/* version of BGP, here BGP-4 */
-#define BGP4_VERSIONS ((char[]) { 0x10 }) /* OID bgp.bgpVersion */
-/* for OID bgp.bgpPeerTable.bgpPeerEntry.bgpPeerNegotiatedVersion */
+#define BGP4_VERSIONS ((char[]) { 0x10 }) /* OID BGP4-MIB::bgpVersion */
+
+/* values for BGP4-MIB::bgpPeerNegotiatedVersion */
#define BGP4_MIB_NEGOTIATED_VER_VALUE 4
#define BGP4_MIB_NEGOTIATED_VER_NO_VALUE 0
+/* values for BGP4-MIB::bgpPeerAdminStatus */
+enum bgp4_admin_status {
+ BGP4_ADMIN_STOP = 1,
+ BGP4_ADMIN_START = 2,
+};
+
u8 snmp_bgp_get_valid(u8 state);
u8 snmp_bgp_getnext_valid(u8 state);
BGP4_MIB_PEER_ENTRY = 1,
};
-enum bgp4_mib_linearized_states {
- BGP4_MIB_S_INVALID = 0, /* state invalid */
- BGP4_MIB_S_START = 1,
- BGP4_MIB_S_BGP,
- BGP4_MIB_S_VERSION,
- BGP4_MIB_S_LOCAL_AS,
- BGP4_MIB_S_PEER_TABLE,
- BGP4_MIB_S_PEER_ENTRY,
- BGP4_MIB_S_PEER_IDENTIFIER,
- BGP4_MIB_S_STATE,
- BGP4_MIB_S_ADMIN_STATUS,
- BGP4_MIB_S_NEGOTIATED_VERSION,
- BGP4_MIB_S_LOCAL_ADDR,
- BGP4_MIB_S_LOCAL_PORT,
- BGP4_MIB_S_REMOTE_ADDR,
- BGP4_MIB_S_REMOTE_PORT,
- BGP4_MIB_S_REMOTE_AS,
- BGP4_MIB_S_RX_UPDATES,
- BGP4_MIB_S_TX_UPDATES,
- BGP4_MIB_S_RX_MESSAGES,
- BGP4_MIB_S_TX_MESSAGES,
- BGP4_MIB_S_LAST_ERROR,
- BGP4_MIB_S_FSM_TRANSITIONS,
- BGP4_MIB_S_FSM_ESTABLISHED_TIME,
- BGP4_MIB_S_RETRY_INTERVAL,
- BGP4_MIB_S_HOLD_TIME,
- BGP4_MIB_S_KEEPALIVE,
- BGP4_MIB_S_HOLD_TIME_CONFIGURED,
- BGP4_MIB_S_KEEPALIVE_CONFIGURED,
- BGP4_MIB_S_ORIGINATION_INTERVAL,
- BGP4_MIB_S_MIN_ROUTE_ADVERTISEMENT,
- BGP4_MIB_S_IN_UPDATE_ELAPSED_TIME,
- BGP4_MIB_S_PEER_TABLE_END,
- BGP4_MIB_S_IDENTIFIER, /* state local identification */
- BGP4_MIB_S_END,
- BGP4_MIB_S_NO_VALUE = 255,
-} PACKED;
-
/* valid values for BGP4_MIB_STATE */
enum bgp4_mib_bgp_states {
BGP4_MIB_IDLE = 1,
STATIC_ASSERT(BGP4_MIB_ESTABLISHED == BS_ESTABLISHED + 1);
/* Traps OID sub-identifiers */
-#define BGP4_MIB_ESTABLISHED_NOTIFICATION 1
-#define BGP4_MIB_BACKWARD_TRANS_NOTIFICATION 2
+enum bgp4_traps_subids {
+ BGP4_MIB_ESTABLISHED_NOTIFICATION = 1,
+ BGP4_MIB_BACKWARD_TRANS_NOTIFICATION = 2,
+};
#endif
#include "proto/bgp/bgp.h"
const char agentx_master_addr[] = AGENTX_MASTER_ADDR;
+const struct oid *agentx_available_mibs[AGENTX_MIB_COUNT + 1] = { 0 };
static void snmp_start_locked(struct object_lock *lock);
static void snmp_sock_err(sock *sk, int err);
static void snmp_stop_timeout(timer *tm);
static void snmp_cleanup(struct snmp_proto *p);
+/*
+ * agentx_get_mib_init - init function for agentx_get_mib()
+ * @p: SNMP instance protocol pool
+ */
+void agentx_get_mib_init(pool *p)
+{
+ const struct oid *src = agentx_available_mibs[AGENTX_MIB_COUNT - 1];
+ size_t size = snmp_oid_size(src);
+ struct oid *dest = mb_alloc(p, size);
+
+ memcpy(dest, src, size);
+ u8 ids = LOAD_U8(src->n_subid);
+
+ if (ids > 0)
+ STORE_U32(dest->ids[ids - 1], LOAD_U32(src->ids[ids - 1]) + 1);
+
+ agentx_available_mibs[AGENTX_MIB_COUNT] = dest;
+}
+
+/*
+ * agentx_get_mib - classify an OID based on MIB prefix
+ *
+ */
+enum agentx_mibs agentx_get_mib(const struct oid *o)
+{
+ enum agentx_mibs mib = AGENTX_MIB_UNKNOWN;
+ for (uint i = 0; i < AGENTX_MIB_COUNT + 1; i++)
+ {
+ ASSERT(agentx_available_mibs[i]);
+ if (snmp_oid_compare(o, agentx_available_mibs[i]) < 0)
+ return mib;
+ mib = (enum agentx_mibs) i;
+ }
+
+ return AGENTX_MIB_UNKNOWN;
+}
+
+
/*
* snmp_rx_skip - skip all received data
* @sk: communication socket
p->bgp_local_as = cf->bgp_local_as;
p->bgp_local_id = cf->bgp_local_id;
p->timeout = cf->timeout;
- // TODO add default value for startup_delay inside bison .Y file
p->startup_delay = cf->startup_delay;
p->pool = p->p.pool;
mib_tree_init(p->pool, p->mib_tree);
snmp_bgp4_start(p);
+ agentx_get_mib_init(p->pool);
return snmp_set_state(p, SNMP_INIT);
}
struct object_lock *lock;
pool *pool; /* a shortcut to the procotol mem. pool */
linpool *lp; /* linpool for bgp_trie nodes */
- slab *request_storage; /* manages storages storage for incomming requests */
enum snmp_proto_state state;
struct mib_tree *mib_tree;
};
+enum agentx_mibs {
+ BGP4_MIB_ID,
+ AGENTX_MIB_COUNT,
+ AGENTX_MIB_UNKNOWN,
+};
+
+extern const struct oid *agentx_available_mibs[AGENTX_MIB_COUNT + 1];
+void agentx_get_mib_init(pool *p);
+enum agentx_mibs agentx_get_mib(const struct oid *o);
+
struct snmp_registration;
struct agentx_response; /* declared in subagent.h */
typedef void (*snmp_reg_hook_t)(struct snmp_proto *p, const struct agentx_response *res, struct snmp_registration *reg);
struct snmp_registration {
node n;
- u8 mib_class;
+ enum agentx_mibs mib;
u32 session_id;
u32 transaction_id;
u32 packet_id;
snmp_reg_hook_t reg_hook_fail; /* hook called when OID registration fail */
};
-//void snmp_tx(sock *sk);
void snmp_startup(struct snmp_proto *p);
void snmp_connected(sock *sk);
void snmp_startup_timeout(timer *tm);
static struct oid *
snmp_oid_prefixize(struct snmp_proto *p, const struct oid *oid, struct snmp_pdu *c)
{
- snmp_vb_to_tx(p, oid, c);
+ snmp_vb_to_tx(c, oid);
struct agentx_varbind *vb = c->sr_vb_start;
bt_assert(vb->reserved == 0);
return &vb->name;
}
struct oid *
-snmp_varbind_set_name_len(struct snmp_proto *p, struct agentx_varbind **vb, u8 len, struct snmp_pdu *c)
+snmp_varbind_set_name_len(struct snmp_pdu *c, struct agentx_varbind **vb, u8 len)
{
struct oid *oid = &(*vb)->name;
/* We need more space */
ASSUME(len >= LOAD_U8(oid->n_subid));
uint diff_size = (len - LOAD_U8(oid->n_subid)) * sizeof(u32);
- if (c->size < diff_size)
+
+ if (snmp_tbuf_reserve(c, diff_size))
{
snmp_log("varbind_set_name_len small buffer");
- snmp_manage_tbuf(p, c);
oid = &(*vb)->name;
}
}
void
-snmp_varbind_duplicate_hdr(struct snmp_proto *p, struct agentx_varbind **vb, struct snmp_pdu *c)
+snmp_varbind_duplicate_hdr(struct snmp_pdu *c, struct agentx_varbind **vb)
{
ASSUME(vb != NULL && *vb != NULL);
uint hdr_size = snmp_varbind_header_size(*vb);
- if (c->size < hdr_size)
- {
+ if (snmp_tbuf_reserve(c, hdr_size))
snmp_log("varbind_duplicate small buffer");
- snmp_manage_tbuf(p, c);
- }
ASSERT(c->size >= hdr_size);
byte *buffer = c->buffer;
}
struct snmp_registration *
-snmp_registration_create(struct snmp_proto *p, u8 mib_class)
+snmp_registration_create(struct snmp_proto *p, enum agentx_mibs mib)
{
struct snmp_registration *r;
r = mb_alloc(p->p.pool, sizeof(struct snmp_registration));
/* will be incremented by snmp_session() macro during packet assembly */
r->transaction_id = p->transaction_id;
r->packet_id = p->packet_id + 1;
- snmp_log("using registration packet_id %u", r->packet_id);
-
- r->mib_class = mib_class;
+ r->mib = mib;
+ snmp_log("using registration packet_id %u", r->packet_id);
add_tail(&p->registration_queue, &r->n);
return r;
}
int
-snmp_registration_match(struct snmp_registration *r, struct agentx_header *h, u8 class)
+snmp_registration_match(struct snmp_registration *r, struct agentx_header *h, enum agentx_mibs mib)
{
snmp_log("snmp_reg_same() r->packet_id %u p->packet_id %u", r->packet_id, h->packet_id);
return
- (r->mib_class == class) &&
+ (r->mib == mib) &&
(r->session_id == h->session_id) &&
(r->transaction_id == h->transaction_id) &&
(r->packet_id == h->packet_id);
{
mib_tree_walk_init(walk, tree);
- snmp_vb_to_tx(c->p, oid, c);
+ snmp_vb_to_tx(c, oid);
mib_node_u *node = mib_tree_find(tree, walk, &c->sr_vb_start->name);
snmp_log("walk_fill got size %u based on lt %u ls %u, calling filler()", size, leaf->type, leaf->size);
- if (size >= c->size)
- {
- snmp_log("walk_fill small buffer size %d to %d", size, c->size);
- snmp_manage_tbuf(c->p, c);
- }
+ if (snmp_tbuf_reserve(c, size))
+ snmp_log("walk_fill small buffer size");
enum snmp_search_res res = leaf->filler(walk, c);
size_t snmp_varbind_size_from_len(uint n_subid, enum agentx_type t, uint len);
int snmp_test_varbind(const struct agentx_varbind *vb);
void *snmp_varbind_data(const struct agentx_varbind *vb);
-struct oid *snmp_varbind_set_name_len(struct snmp_proto *p, struct agentx_varbind **vb, u8 len, struct snmp_pdu *c);
-void snmp_varbind_duplicate_hdr(struct snmp_proto *p, struct agentx_varbind **vb, struct snmp_pdu *c);
+struct oid *snmp_varbind_set_name_len(struct snmp_pdu *c, struct agentx_varbind **vb, u8 len);
+void snmp_varbind_duplicate_hdr(struct snmp_pdu *c, struct agentx_varbind **vb);
/*
* AgentX - PDU headers, types, contexts
* Helpers, Misc, Debugging
*
*/
-struct snmp_registration *snmp_registration_create(struct snmp_proto *p, u8 mib_class);
-int snmp_registration_match(struct snmp_registration *r, struct agentx_header *h, u8 class);
+struct snmp_registration *snmp_registration_create(struct snmp_proto *p, enum agentx_mibs mib);
+int snmp_registration_match(struct snmp_registration *r, struct agentx_header *h, enum agentx_mibs mib);
void snmp_dump_packet(byte *pkt, uint size);
void snmp_oid_dump(const struct oid *oid);
* snmp_register_ack - handle registration response
* @p: SNMP protocol instance
* @res: header of agentx-Response-PDU
- * @class: MIB subtree associated with agentx-Register-PDU
+ * @mib: MIB subtree identifier
*/
void
-snmp_register_ack(struct snmp_proto *p, struct agentx_response *res, u8 class)
+snmp_register_ack(struct snmp_proto *p, struct agentx_response *res, const struct oid *oid)
{
+ enum agentx_mibs mib = agentx_get_mib(oid);
+
struct snmp_registration *reg;
WALK_LIST(reg, p->registration_queue)
{
- if (snmp_registration_match(reg, &res->h, class))
+ if (snmp_registration_match(reg, &res->h, mib))
{
rem_node(®->n);
p->registrations_to_ack--;
#define TIMEOUT_SIZE sizeof(u32) /* 1B timeout, 3B zero padding */
/* Make sure that we have enough space in TX-buffer */
- if (c.size < AGENTX_HEADER_SIZE + TIMEOUT_SIZE + snmp_oid_size(oid) +
- + snmp_str_size(cf->description))
- {
+ uint s = AGENTX_HEADER_SIZE + TIMEOUT_SIZE + snmp_oid_size(oid) +
+ snmp_str_size(cf->description);
+ if (snmp_tbuf_reserve(&c, s))
snmp_log("agentx-Open-PDU small buffer");
- snmp_manage_tbuf(p, &c);
- }
struct agentx_header *h = (void *) c.buffer;
ADVANCE(c.buffer, c.size, AGENTX_HEADER_SIZE);
c.buffer = snmp_put_oid(c.buffer, oid);
c.buffer = snmp_put_str(c.buffer, cf->description);
- uint s = update_packet_size(h, c.buffer);
+ s = update_packet_size(h, c.buffer);
sk_send(sk, s);
#undef TIMEOUT_SIZE
}
struct snmp_pdu c;
snmp_pdu_context(&c, p, sk);
-#define UPTIME_SIZE sizeof(STATIC_OID(4))
-#define TRAP0_HEADER_SIZE sizeof(STATIC_OID(6))
+#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 */
uint sz = AGENTX_HEADER_SIZE + TRAP0_HEADER_SIZE + snmp_oid_size(oid) \
+ size;
sz += UPTIME_SIZE;
/* Make sure that we have enough space in TX-buffer */
- if (c.size < sz)
- {
+ if (snmp_tbuf_reserve(&c, sz))
snmp_log("agentx-Notify-PDU small buffer");
- snmp_manage_tbuf(p, &c);
- }
struct agentx_header *h = (void *) c.buffer;
ADVANCE(c.buffer, c.size, AGENTX_HEADER_SIZE);
uint sz = AGENTX_HEADER_SIZE + snmp_oid_size(oid) +
((bound > 1) ? BOUND_SIZE : 0);
- if (c.size < sz)
- {
+ if (snmp_tbuf_reserve(&c, sz))
snmp_log("agentx-Register-PDU small buffer");
- snmp_manage_tbuf(p, &c);
- }
struct agentx_header *h = (void *) c.buffer;
ADVANCE(c.buffer, c.size, AGENTX_HEADER_SIZE);
snmp_pdu_context(&c, p, sk);
#define REASON_SIZE sizeof(u32)
- if (c.size < AGENTX_HEADER_SIZE + REASON_SIZE)
- {
+ if (snmp_tbuf_reserve(&c, AGENTX_HEADER_SIZE + REASON_SIZE))
snmp_log("agentx-Close-PDU small buffer");
- snmp_manage_tbuf(p, &c);
- }
struct agentx_header *h = (void *) c.buffer;
ADVANCE(c.buffer, c.size, AGENTX_HEADER_SIZE);
struct snmp_pdu c;
snmp_pdu_context(&c, p, sk);
- if (c.size < AGENTX_HEADER_SIZE)
- {
+ if (snmp_tbuf_reserve(&c, AGENTX_HEADER_SIZE))
snmp_log("agentx-TestSet-PDU small buffer");
- snmp_manage_tbuf(p, &c);
- }
res = prepare_response(p, &c);
struct snmp_pdu c;
snmp_pdu_context(&c, p, p->sock);
- if (c.size < sizeof(struct agentx_response))
- {
+ if (snmp_tbuf_reserve(&c, sizeof(struct agentx_response)))
snmp_log("parse_sets_pdu small buffer");
- snmp_manage_tbuf(p, &c);
- }
struct agentx_response *r = prepare_response(p, &c);
// TODO more direct path to mib-specific code
TRACE(D_PACKETS, "SNMP received agentx-Response-PDU with error %u", r->error);
byte *pkt = res + sizeof(struct agentx_response);
- struct oid *failed = (void *) pkt;
- snmp_register_ack(p, r, snmp_get_mib_class(failed));
+ struct oid *failed = (struct oid *) pkt;
+ snmp_register_ack(p, r, failed);
break;
/*
struct agentx_response *r = (void *) pkt;
struct agentx_header *h = (void *) r;
- /* TODO make it asynchronous for better speed */
switch (p->state)
{
case SNMP_INIT:
case SNMP_REGISTER:;
pkt += AGENTX_HEADER_SIZE;
- const struct oid *oid = (void *) pkt;
-
- snmp_register_ack(p, r, snmp_get_mib_class(oid));
+ const struct oid *oid = (struct oid *) pkt;
+ snmp_register_ack(p, r, oid);
if (p->registrations_to_ack == 0)
snmp_set_state(p, SNMP_CONN);
}
}
-/*
- * snmp_get_mib_class - classify MIB tree belongings of OID
- * @oid: OID to be classified based on prefix
- */
-u8
-snmp_get_mib_class(const struct oid *oid)
-{
- // TODO check code paths for oid->n_subid < 3
- if (oid->prefix != SNMP_MGMT && oid->ids[0] != SNMP_MIB_2)
- return SNMP_CLASS_INVALID;
-
- switch (oid->ids[1])
- {
- case SNMP_BGP4_MIB:
- return SNMP_CLASS_BGP;
-
- default:
- return SNMP_CLASS_END;
- }
-}
-
static inline struct oid *
snmp_oid_prefixize_unsafe(struct oid *dest, const struct oid *src)
{
/*
* snmp_vb_to_tx - create varbind from RX buffer OID
- * @p: SNMP protocol instance
- * @oid: object identifier located in RX buffer
* @c: PDU context
+ * @oid: object identifier located in RX buffer
*
* Create NULL initialized VarBind inside TX buffer (from @c) whose vb->name is
* @oid. The @oid prefixed if possible. The result is stored in @c->sr_vb_start.
*/
void
-snmp_vb_to_tx(struct snmp_proto *p, const struct oid *oid, struct snmp_pdu *c)
+snmp_vb_to_tx(struct snmp_pdu *c, const struct oid *oid)
{
uint vb_hdr_size = snmp_varbind_hdr_size_from_oid(oid);
- if (c->size < vb_hdr_size)
- {
+ if (snmp_tbuf_reserve(c, vb_hdr_size))
snmp_log("SNMP vb_to_tx small buffer");
- snmp_manage_tbuf(p, c);
- }
ASSERT(c->size >= vb_hdr_size);
struct agentx_varbind *vb = (void *) c->buffer;
{
STORE_U32(res->error, (u16) err);
// TODO deal with auto-incrementing of snmp_pdu context c.ind
- // FIXME for packets with errors reset reset payload size to null (by move c.buffer appropriately)
if (err != AGENTX_RES_NO_ERROR && err != AGENTX_RES_GEN_ERROR)
{
TRACE(D_PACKETS, "Last PDU resulted in error %u", err);
/*
* AgentX GetPDU, GetNextPDU and GetBulkPDU
*/
+
+/* agentx-Get-PDU */
void
snmp_get_pdu(struct snmp_proto *p, struct snmp_pdu *c, const struct oid *o_start, struct mib_walk_state *walk)
{
snmp_set_varbind_type(c->sr_vb_start, snmp_search_res_to_type(res));
}
+/* agentx-GetNext-PDU */
int
snmp_get_next_pdu(struct snmp_proto *p, struct snmp_pdu *c, const struct oid *o_start, struct mib_walk_state *walk)
{
return res == SNMP_SEARCH_OK;
}
+/* agentx-GetBulk-PDU */
void
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)
{
struct agentx_getbulk *bulk_info = (void *) pkt;
ADVANCE(pkt, pkt_size, sizeof(struct agentx_getbulk));
- //TODO: bulk_state = AGENTX_BULK_STATE_INITIALIZER(bulk_info);
bulk_state = (struct agentx_bulk_state) {
.getbulk = {
.non_repeaters = LOAD_U32(bulk_info->non_repeaters),
if (h->type == AGENTX_GET_BULK_PDU)
{
+ // TODO: an error for now
}
/* We update the error, index pair on the beginning of the packet. */
}
/*
- * snmp_manage_tbuf - TODO
- */
-void
-snmp_manage_tbuf(struct snmp_proto *p, struct snmp_pdu *c)
-{
- sock *sk = p->sock;
- int diff;
- if (c->sr_vb_start != NULL)
- diff = (void *) c->sr_vb_start - (void *) sk->tbuf;
-
- snmp_log("snmp_manage_tbuf2()");
- sk_set_tbsize(sk, sk->tbsize + 2048);
- c->size += 2048;
-
- if (c->sr_vb_start != NULL)
- c->sr_vb_start = (struct agentx_varbind *) (sk->tbuf + diff);
-}
-
-/*
- * snmp_manage_tbuf2 - handle situation with too short transmit buffer
- * @p: SNMP protocol instance
- * @c: transmit packet context to use
+ * snmp_tbuf_reserve - TODO
*
- * Important note: After managing insufficient buffer size all in buffer pointers
- * are invalidated!
*/
-void
-snmp_manage_tbuf2(struct snmp_proto *p, void **ptr, struct snmp_pdu *c)
+int
+snmp_tbuf_reserve(struct snmp_pdu *c, size_t size)
{
- sock *sk = p->sock;
- int diff;
- if (ptr)
- diff = *ptr - (void *) sk->tbuf;
+ if (size >= c->size)
+ {
+ struct snmp_proto *p = c->p;
+ sock *sk = p->sock;
- snmp_log("snmp_manage_tbuf()");
- sk_set_tbsize(sk, sk->tbsize + 2048);
- c->size += 2048;
+ int diff;
+ if (c->sr_vb_start != NULL)
+ diff = (char *) c->sr_vb_start - (char *) sk->tbuf;
- if (ptr)
- *ptr = sk->tbuf + diff;
-}
+ snmp_log("snmp_tbuf_reserve()");
+ sk_set_tbsize(sk, sk->tbsize + 2048);
+ c->size += 2048;
-void
-snmp_tbuf_reserve(struct snmp_pdu *c, size_t size)
-{
- if (size > c->size)
- {
- snmp_manage_tbuf(c->p, c);
+ if (c->sr_vb_start != NULL)
+ c->sr_vb_start = (struct agentx_varbind *) (sk->tbuf + diff);
+
+ return 1;
}
+
+ return 0;
}
/*
#include "nest/bird.h"
#include "snmp.h"
+#include "lib/macro.h"
void snmp_start_subagent(struct snmp_proto *p);
void snmp_stop_subagent(struct snmp_proto *p);
#define SNMP_DEFAULT_CONTEXT 0
-enum SNMP_CLASSES {
- SNMP_CLASS_INVALID = 0,
- SNMP_CLASS_BGP = 1,
- SNMP_CLASS_OSPF,
- SNMP_CLASS_END,
-};
-
enum agentx_type {
AGENTX_INTEGER = 2,
AGENTX_OCTET_STRING = 4,
SNMP_SEARCH_END_OF_VIEW = 3,
};
-#define AGENTX_ADMIN_STOP 1
-#define AGENTX_ADMIN_START 2
#define AGENTX_PRIORITY 127
#define SNMP_ORDER 0
#endif
+/* We recommend using STORE_U32 over VALUE_U32 when possible */
#ifdef SNMP_NATIVE
-#define STORE_U32(dest, val) ((dest) = (u32) (val))
-#define STORE_U16(dest, val) ((dest) = (u16) (val))
-#define STORE_U8(dest, val) ((dest) = (u8) (val))
+#define STORE_U32(dest, val) ((u32) ((dest) = (u32) (val)))
+#define STORE_U16(dest, val) ((u16) ((dest) = (u16) (val)))
+#define STORE_U8(dest, val) ((u8) ((dest) = (u8) (val)))
#define STORE_PTR(ptr, val) (*((u32 *) (ptr)) = (u32) (val))
+#define VALUE_U32(val) ((u32) (val))
+#define VALUE_U16(val) ((u16) (val))
+#define VALUE_U8(val) ((u8) (val))
+
#define LOAD_U32(src) *((u32 *) &(src))
#define LOAD_U16(src) *((u16 *) &(src))
#define LOAD_U8(src) *((u8 *) &(src))
#define STORE_U8(dest, val) put_u8(&(dest), (val))
#define STORE_PTR(ptr, val) put_u32(ptr, val)
+#define VALUE_U32(val) htonl(val)
+#define VALUE_U16(val) htons(val)
+#define VALUE_U8(val) ((u8) (val))
+
+
#define LOAD_U32(src) get_u32(&(src))
#define LOAD_U16(src) get_u16(&(src))
#define LOAD_U8(src) get_u8(&(src))
u32 ids[sbids]; \
}
+#define VALUE_U32_HELPER(x) VALUE_U32(x),
+#define STATIC_OID_INITIALIZER(sbids, pref, ...) \
+ { \
+ .n_subid = VALUE_U8(sbids), \
+ .prefix = VALUE_U8(pref), \
+ .include = VALUE_U8(0), \
+ .reserved = VALUE_U8(0), \
+ .ids = { MACRO_FOREACH(VALUE_U32_HELPER, __VA_ARGS__) }, \
+ }
+
/* enforced by MIB tree, see mib_tree.h for more info */
#define OID_MAX_LEN 32
/* SNMP PDU info */
struct snmp_pdu {
struct snmp_proto *p;
- /* TX buffer */
+
+ /* TX buffer */
byte *buffer; /* pointer to buffer */
uint size; /* unused space in buffer */
void snmp_unregister(struct snmp_proto *p, struct oid *oid, uint index, uint len, uint contid);
void snmp_notify_pdu(struct snmp_proto *p, struct oid *oid, void *data, uint size, int include_uptime);
-void snmp_manage_tbuf(struct snmp_proto *p, struct snmp_pdu *c);
+int snmp_tbuf_reserve(struct snmp_pdu *c, size_t bytes);
-void snmp_vb_to_tx(struct snmp_proto *p, const struct oid *oid, struct snmp_pdu *c);
+void snmp_vb_to_tx(struct snmp_pdu *c, const struct oid *oid);
u8 snmp_get_mib_class(const struct oid *oid);
void snmp_register_mibs(struct snmp_proto *p);
/* MIB modules */
void snmp_bgp4_start(struct snmp_proto *p);
-
#if 1
#define snmp_log(...) log(L_INFO "SNMP " __VA_ARGS__)
#else