/* snmp_register(struct snmp_proto *p, struct oid *oid, uint index, uint len, u8 is_instance, uint contid) */
snmp_register(p, oid, 1, 0, SNMP_REGISTER_TREE, SNMP_DEFAULT_CONTEXT);
}
-
-#if 0
- u32 bgp_peer_entry[] = { 1, 15, 3, 1, 1 };
- u32 bound = 24;
- HASH_WALK(p->bgp_hash, next, peer)
- {
- if (peer->flags & SNMP_BGP_P_REGISTERED)
- continue;
-
- struct bgp_proto *bgp = (struct bgp_proto *) peer->config->c.proto;
-
- struct snmp_register *registering = snmp_register_create(p, SNMP_BGP4_MIB);
-
- struct oid *oid = mb_alloc(p->pool, snmp_oid_sizeof(9));
- STORE_U8(oid->n_subid, 9);
- STORE_U8(oid->prefix, SNMP_MGMT);
-
- for (uint i = 0; i < ARRAY_SIZE(bgp_peer_entry); i++)
- STORE_U32(oid->ids[i], bgp_peer_entry[i]);
- ip4_to_oid(oid, ipa_to_ip4(bgp->remote_ip));
-
- /* index is position of x in .1.3.6.1.2.15.3.1.x (1-based) */
- snmp_register(p, oid, bound, 9, SNMP_REGISTER_INSTANCE, peer->context_id);
-
- registering->oid = oid;
- add_tail(&p->register_queue, ®istering->n);
- p->register_to_ack++;
- }
- HASH_WALK_END;
-#endif
}
static int
{
struct oid *oid = &vb->name;
uint size = c->size - snmp_varbind_header_size(vb);
- uint UNUSED contid = c->context;
byte *pkt;
ip_addr addr;
byte *pkt;
if (is_static(state))
{
- pkt = bgp_fill_static(p, vb, c->buffer, c->size, c->context, c->byte_ord, state);
+ pkt = bgp_fill_static(p, vb, c->buffer, c->size, 0, c->byte_ord, state);
ADVANCE(c->buffer, c->size, pkt - c->buffer);
return;
}
#define SNMP_CFG ((struct snmp_config *) this_proto)
-struct snmp_bond *this_bond = NULL;
-
CF_DECLS
CF_KEYWORDS(SNMP, PROTOCOL, BPG, LOCAL, AS, REMOTE, ADDRESS, PORT, DESCRIPTION,
init_list(&SNMP_CFG->bgp_entries);
SNMP_CFG->bonds = 0;
- /* We always have the default context */
- SNMP_CFG->contexts = 1;
SNMP_CFG->local_ip = IPA_NONE;
SNMP_CFG->remote_ip = ipa_build4(127,0,0,1);
proto_name ;
-snmp_context:
- /* empty */ {
- if (!this_bond)
- this_bond = cfg_alloc(sizeof(struct snmp_bond));
-
- this_bond->context = NULL;
- }
- | CONTEXT DEFAULT {
- if (!this_bond)
- this_bond = cfg_alloc(sizeof(struct snmp_bond));
-
- this_bond->context = NULL;
- }
- | CONTEXT text {
- if(!this_bond)
- this_bond = cfg_alloc(sizeof(struct snmp_bond));
-
- this_bond->context = $2;
- SNMP_CFG->contexts++;
- }
- ;
-
-snmp_bgp_bond: BGP symbol snmp_context
+snmp_bgp_bond: BGP symbol
{
/* the snmp_context rule sets the correct value of this_bond */
- if (!this_bond)
- this_bond = cfg_alloc(sizeof(struct snmp_bond));
-
+ struct snmp_bond *this_bond = cfg_alloc(sizeof(struct snmp_bond));
this_bond->type = SNMP_BGP;
cf_assert_symbol($2, SYM_PROTO);
if (!this_bond->proto) cf_error("BGP protocol %s not found", $2->name);
add_tail(&SNMP_CFG->bgp_entries, &this_bond->n);
SNMP_CFG->bonds++;
-
- this_bond = NULL;
}
CF_CODE
p->timeout = cf->timeout;
- /* used when assigning the context ids in s_cont_create() */
- p->context_max = 1;
- p->context_id_map = NULL;
-
return P;
}
}
HASH_FREE(p->bgp_hash);
- HASH_FREE(p->context_hash);
- mb_free(p->context_id_map);
- p->context_id_map = NULL;
rfree(p->lp);
p->bgp_trie = NULL;
tm_set(p->ping_timer, current_time() + p->timeout S);
}
-/* this function is internal and shouldn't be used outside the snmp module */
-void
-snmp_reconnect(timer *tm)
-{
- struct snmp_proto *p = tm->data;
- ASSUME(p->sock);
- snmp_connected(p->sock);
-}
-
/* this function is internal and shouldn't be used outside the snmp module */
void
snmp_sock_disconnect(struct snmp_proto *p, int reconnect)
tm_set(p->startup_timer, current_time() + p->timeout S);
}
+/* this function is internal and shouldn't be used outside the snmp module */
+void
+snmp_reconnect(timer *tm)
+{
+ struct snmp_proto *p = tm->data;
+ if (p->state == SNMP_STOP ||
+ p->state == SNMP_DOWN)
+ return;
+
+ // TODO is SNMP_RESET really needed ?
+ if (p->state == SNMP_INIT ||
+ p->state == SNMP_RESET)
+ snmp_startup(p);
+
+ if (!p->sock)
+ snmp_start_locked(p->lock);
+ else
+ snmp_connected(p->sock);
+}
+
+
/* this function is internal and shouldn't be used outside the snmp module */
void
snmp_startup(struct snmp_proto *p)
/* We create copy of bonds to BGP protocols. */
HASH_INIT(p->bgp_hash, p->pool, 10);
- HASH_INIT(p->context_hash, p->pool, 10);
-
- /* We always have at least the default context */
- p->context_id_map_size = cf->contexts;
- p->context_id_map = mb_allocz(p->pool, cf->contexts * sizeof(struct snmp_context *));
- //log(L_INFO "number of context allocated %d", cf->contexts);
-
- struct snmp_context *defaultc = mb_alloc(p->pool, sizeof(struct snmp_context));
- defaultc->context = "";
- defaultc->context_id = 0;
- defaultc->flags = 0; /* TODO Default context fl. */
- HASH_INSERT(p->context_hash, SNMP_H_CONTEXT, defaultc);
-
- p->context_id_map[0] = defaultc;
struct snmp_bond *b;
WALK_LIST(b, cf->bgp_entries)
trie_add_prefix(p->bgp_trie, &net, IP4_MAX_PREFIX_LENGTH, IP4_MAX_PREFIX_LENGTH);
HASH_INSERT(p->bgp_hash, SNMP_HASH, peer);
-
- /* Handle non-default context */
- if (b->context)
- {
- const struct snmp_context *c = snmp_cont_create(p, b->context);
- peer->context_id = c->context_id;
- }
}
}
- ASSUME(cf->contexts == p->context_max);
-
snmp_startup(p);
return PS_START;
}
{
if (!strcmp(b1->proto->name, b2->proto->name))
goto skip;
-
- /* Both bonds use default context */
- if (!b1->context && !b2->context)
- goto skip;
-
- /* Both bonds use same non-default context */
- if (b1->context && b2->context && !strcmp(b1->context, b2->context))
- goto skip;
}
return 0;
/* hash table only store ip4 addresses */
#define SNMP_HASH_LESS(ip1, ip2) SNMP_HASH_LESS4(ip1,ip2)
-/* context hash table macros */
-#define SNMP_H_CONTEXT_KEY(c) c->context
-#define SNMP_H_CONTEXT_NEXT(c) c->next
-#define SNMP_H_CONTEXT_EQ(s1,s2) strcmp(s1,s2)
-#define SNMP_H_CONTEXT_FN(s) mem_hash(s, strlen(s))
-
struct snmp_bond {
node n;
struct proto_config *proto;
u8 type;
- const char *context;
};
struct snmp_config {
u8 priority;
//struct iface *iface;
u32 bonds;
- uint contexts; /* Number of all conetexts including the default */
const char *description;
list bgp_entries;
// TODO add support for subagent oid identification
struct snmp_bgp_peer {
const struct bgp_config *config;
ip_addr peer_ip;
- uint context_id;
u8 flags;
struct snmp_bgp_peer *next;
};
struct oid *oid;
};
-struct snmp_context {
- const char *context; /* string name */
- //uint length; /* strlen() of name */
- uint context_id;
- u8 flags;
- struct snmp_context *next;
-};
-
struct snmp_proto {
struct proto p;
struct object_lock *lock;
// map
struct f_trie *bgp_trie;
HASH(struct snmp_bgp_peer) bgp_hash;
- HASH(struct snmp_context) context_hash;
- struct snmp_context **context_id_map;
- uint context_id_map_size;
- uint context_max;
struct tbf rl_gen;
timer *ping_timer;
return 0;
}
-/*
-inline uint
-snmp_context_size(struct agentx_context *c)
-{
- return (c && c->length) ? snmp_str_size_from_len(c->length) : 0;
-}
-*/
-
struct agentx_varbind *
snmp_create_varbind(byte *buf, struct oid *oid)
{
return type_arr[r];
}
-inline const struct snmp_context *
-snmp_cont_find(struct snmp_proto *p, const char *name)
-{
- u32 *ptr = mb_alloc(p->p.pool, 4 * sizeof(u32));
- *ptr = 1;
- ptr[2] = 4;
- (void)ptr[1]; (void)ptr[0]; (void)ptr[2];
- mb_free(ptr);
- return HASH_FIND(p->context_hash, SNMP_H_CONTEXT, name);
-}
-
-inline const struct snmp_context *
-snmp_cont_get(struct snmp_proto *p, uint cont_id)
-{
- if (cont_id >= p->context_max)
- return NULL;
-
- return p->context_id_map[cont_id];
-}
-
-inline const struct snmp_context *
-snmp_cont_create(struct snmp_proto *p, const char *name)
-{
- const struct snmp_context *c = snmp_cont_find(p, name);
-
- if (c)
- return c;
-
- struct snmp_context *c2;
- c2 = mb_alloc(p->p.pool, sizeof(struct snmp_context));
- c2->context = name;
- c2->context_id = p->context_max++;
- c2->flags = 0;
-
- u32 *ptr = mb_alloc(p->p.pool, 4 * sizeof(u32));
- *ptr = 1;
- ptr[2] = 4;
- (void)ptr[1]; (void)ptr[0]; (void)ptr[2];
- mb_free(ptr);
-
- HASH_INSERT(p->context_hash, SNMP_H_CONTEXT, c2);
-
- if (c2->context_id >= p->context_id_map_size)
- {
- // TODO: allocate more than needed for better speed
- p->context_id_map_size = c2->context_id + 1;
- p->context_id_map = mb_realloc(p->context_id_map, p->context_id_map_size * sizeof(struct snmp_context *));
- }
-
- p->context_id_map[c2->context_id] = c2;
-
- return c2;
-}
uint snmp_varbind_header_size(struct agentx_varbind *vb);
uint snmp_varbind_size(struct agentx_varbind *vb, int byte_ord);
int snmp_test_varbind(const struct agentx_varbind *vb);
-//uint snmp_context_size(struct agentx_context *c);
void snmp_oid_copy(struct oid *dest, const struct oid *src);
void snmp_dump_packet(byte *pkt, uint size);
-const struct snmp_context *snmp_cont_find(struct snmp_proto *p, const char *name);
-const struct snmp_context *snmp_cont_get(struct snmp_proto *p, uint context_id);
-const struct snmp_context *snmp_cont_create(struct snmp_proto *p, const char *name);
-
enum agentx_type snmp_search_res_to_type(enum snmp_search_res res);
int agentx_type_size(enum agentx_type t);
/* Register-PDU / Unregister-PDU */
static void
-un_register_pdu(struct snmp_proto *p, struct oid *oid, uint len, uint index, u8 type, u8 is_instance, uint contid)
+un_register_pdu(struct snmp_proto *p, struct oid *oid, uint len, uint index, u8 type, u8 is_instance, uint UNUSED contid)
{
const struct snmp_config *cf = SKIP_BACK(struct snmp_config, cf, p->p.cf);
sock *sk = p->sock;
/* conditional +4 for upper-bound (optinal field) */
uint sz = AGENTX_HEADER_SIZE + snmp_oid_size(oid) + ((len > 1) ? 4 : 0);
- const struct snmp_context *sc = NULL;
- if (contid)
- {
- sc = snmp_cont_get(p, contid);
- sz += snmp_str_size(sc->context);
- }
-
if (c.size < sz)
snmp_manage_tbuf(p, &c);
SNMP_SESSION(h, p);
c.byte_ord = h->flags & AGENTX_NETWORK_BYTE_ORDER;
- SNMP_NON_DEFAULT_CONTEXT(h, c, contid);
-
struct agentx_un_register_hdr *ur = (struct agentx_un_register_hdr *) c.buffer;
/* do not override timeout */
return AGENTX_HEADER_SIZE;
}
- /* The agentx-Close-PDU must not have non-default context */
-
snmp_simple_response(p, AGENTX_RES_NO_ERROR, 0);
snmp_sock_disconnect(p, 1); // TODO: should we try to reconnect (2nd arg) ??
return AGENTX_HEADER_SIZE;
#if 0
static void UNUSED
addagentcaps_pdu(struct snmp_proto *p, struct oid *cap, char *descr,
- uint descr_len, struct agentx_context *c)
+ uint descr_len)
{
ASSUME(descr != NULL && descr_len > 0);
sock *sk = p->sock;
byte *buf = sk->tpos;
uint size = sk->tbuf + sk->tbsize - sk->tpos;
- if (size < AGENTX_HEADER_SIZE + snmp_context_size(c) + snmp_oid_size(cap) + snmp_str_size_from_len(descr_len))
+ if (size < AGENTX_HEADER_SIZE + snmp_oid_size(cap) + snmp_str_size_from_len(descr_len))
{
/* TO-DO need more mem */
return;
if (c && c->length)
{
SNMP_HAS_CONTEXT(h);
- in_pkt = snmp_put_nstr(buf, c->context, c->length) - buf;
ADVANCE(buf, size, in_pkt);
}
}
static void UNUSED
-removeagentcaps_pdu(struct snmp_proto *p, struct oid *cap, struct agentx_context *c)
+removeagentcaps_pdu(struct snmp_proto *p, struct oid *cap)
{
sock *sk = p->sock;
byte *buf = sk->tpos;
uint size = sk->tbuf + sk->tbsize - sk->tpos;
- if (size < AGENTX_HEADER_SIZE + snmp_context_size(c) + snmp_oid_size(cap))
+ if (size < AGENTX_HEADER_SIZE + snmp_oid_size(cap))
{
/* TO-DO need more mem */
return;
if (c && c->length)
{
SNMP_HAS_CONTEXT(h);
- in_pkt = snmp_put_nstr(buf, c->context, c->length) - buf;
ADVANCE(buf, size, in_pkt);
}
res = prepare_response(p, &c);
- uint clen;
- const char *context;
- SNMP_LOAD_CONTEXT(h, pkt, context, clen);
-
- if (size < clen)
- return 0;
-
- if (pkt_size < clen)
- {
- c.error = AGENTX_RES_PARSE_ERROR;
-
- goto error;
- }
-
- ADVANCE(pkt, pkt_size, clen);
- size -= clen;
-
/* 0 if there is piece, that we cannot set */
int all_possible = 0;
/* the all_possible is currently hard-coded with no support for writing to mib
* variables, when implementing the mentioned support, change the initializer
* to 1
*/
-
#if 0
// TODO think about future value setting data structure
//struct agentx_transaction *tr = mb_alloc(...);
}
mb_free(tr);
#endif
-
+ goto error;
error:
s = update_packet_size(p, sk->tpos, c.buffer);
struct agentx_response *r = prepare_response(p, &c);
- uint clen;
- const char *context;
- SNMP_LOAD_CONTEXT(h, pkt, context, clen);
-
- if (size < snmp_str_size_from_len(clen))
- return 0;
-
if (size < pkt_size)
{
c.error = AGENTX_RES_PARSE_ERROR;
goto error;
}
- ADVANCE(pkt, size, snmp_str_size_from_len(clen));
- // TODO: work with context
-
// TODO: free resource allocated by parse_test_set_pdu()
// TODO: do something meaningful
//mb_free(tr);
byte *pkt = buf;
ADVANCE(pkt, size, AGENTX_HEADER_SIZE);
- uint clen;
- const char *context;
- SNMP_LOAD_CONTEXT((struct agentx_header *) buf, pkt, context, clen);
-
- if (size < snmp_str_size_from_len(clen))
- return;
-
- ADVANCE(pkt, size, snmp_str_size_from_len(clen));
const struct oid *oid = (void *) pkt;
snmp_register_ack(p, h, snmp_get_mib_class(oid));
// TODO better handling of endianness
c.byte_ord = 0; /* use little-endian */
- uint clen; /* count of characters in context (without last '\0') */
- const char *context; /* pointer to RX-buffer context */
-
- /* moves with pkt; assign context, clen */
- SNMP_LOAD_CONTEXT(h, pkt, context, clen);
-
- /*
- * We need more data; for valid response we need to know full
- * header picture, including the context octet string
- */
- if (size < clen)
- goto wait;
-
- /*
- * It is a malformed packet if the context octet string should be longer than
- * whole packet.
- */
- if (pkt_size < clen)
- {
- c.error = AGENTX_RES_PARSE_ERROR;
- c.index = 0;
- ret = MIN(size, pkt_size + AGENTX_HEADER_SIZE);
- goto error;
- }
-
- /* The RFC does not consider the context octet string as a part of a header */
- ADVANCE(pkt, pkt_size, clen);
- size -= clen;
-
- /* FIXME add support for c.context hashing
- c.context = ...
- */
-
/*
* Get-Bulk processing stops if all the varbind have type END_OF_MIB_VIEW
* has_any is true if some varbind has type other than END_OF_MIB_VIEW
if (c.size < sizeof(struct agentx_response))
{
snmp_manage_tbuf(p, &c);
- // TODO renew pkt, pkt_start pointers context clen
+ // TODO renew pkt, pkt_start pointers
}
struct agentx_response *response_header = prepare_response(p, &c);
goto free;
partial:
- /* The context octet is not added into response pdu. */
-
/* need to tweak RX buffer packet size */
(c.byte_ord) ? put_u32(&h->payload, pkt_size) : (h->payload = pkt_size);
- *skip = AGENTX_HEADER_SIZE + snmp_str_size_from_len(clen);
+ *skip = AGENTX_HEADER_SIZE;
/* number of bytes parsed from RX-buffer */
ret = pkt - pkt_start;
working only with o_start, o_end allocated in heap (not from buffer)*/
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 *c,
+ struct oid *o_curr, struct snmp_pdu UNUSED *c,
enum snmp_search_res *result)
{
ASSUME(o_start != NULL);
switch (o_curr->ids[1])
{
case SNMP_BGP4_MIB:
- r = snmp_bgp_search2(p, &o_curr, o_end, c->context);
+ r = snmp_bgp_search2(p, &o_curr, o_end, 0);
if (r == SNMP_SEARCH_OK)
{
str[length] = '\0'; /* set term. char */ \
buf += 4 + snmp_str_size_from_len(length); })
-#define SNMP_LOAD_CONTEXT(hdr, buf, cont, cont_len) ({ \
- if (cont = NULL, cont_len = 0, (hdr)->flags & AGENTX_NON_DEFAULT_CONTEXT) \
- LOAD_STR((buf), (cont), (cont_len), \
- (hdr)->flags & AGENTX_NETWORK_BYTE_ORDER); })
-
-#define SNMP_COPY_CONTEXT(proto, hdr, buf, cont, cont_len) ({ \
- cont = NULL; cont_len = 0; \
- if (hdr->flags & AGENTX_NON_DEFAULT_CONTEXT) \
- COPY_STR(proto, buf, cont, cont_len, \
- (hdr)->flags & AGENTX_NETWORK_BYTE_ORDER) })
-
#define SNMP_HAS_CONTEXT(hdr) \
hdr->flags |= AGENTX_NON_DEFAULT_CONTEXT
-#define SNMP_NON_DEFAULT_CONTEXT(hdr,pdu,contid) ({ \
- if (contid) { \
- SNMP_HAS_CONTEXT(hdr); \
- snmp_put_str((c).buffer, (sc)->context); \
- ADVANCE((c).buffer, (c).size, snmp_str_size((sc)->context)); \
- } })
-
#define SNMP_PUT_OID(buf, size, oid, byte_ord) \
({ \
struct agentx_varbind *vb = (void *) buf; \
.buffer = sk->tpos, \
.size = sk->tbuf + sk->tbsize - sk->tpos, \
.error = AGENTX_RES_NO_ERROR, \
- .context = 0, \
.index = 0, \
}
struct snmp_pdu {
byte *buffer; /* pointer to buffer */
uint size; /* unused space in buffer */
- uint context; /* context hash */
int byte_ord; /* flag signaling NETWORK_BYTE_ORDER */
enum agentx_response_err error; /* storage for result of current action */
uint index; /* index on which the error was found */