From 728e968ba79b7fa47c0fcd2d67185f972ce45a5a Mon Sep 17 00:00:00 2001 From: Vojtech Vilimek Date: Wed, 18 Oct 2023 18:06:24 +0200 Subject: [PATCH 1/5] SNMP: Refactoring - Comments, Logging --- proto/snmp/bgp_mib.c | 102 ++++++++++---------- proto/snmp/config.Y | 17 ++-- proto/snmp/snmp.c | 42 +++------ proto/snmp/snmp.h | 6 +- proto/snmp/snmp_utils.c | 35 ++++--- proto/snmp/subagent.c | 200 ++++++++++++++++++++-------------------- proto/snmp/subagent.h | 6 +- 7 files changed, 203 insertions(+), 205 deletions(-) diff --git a/proto/snmp/bgp_mib.c b/proto/snmp/bgp_mib.c index 46e09789..59fb7524 100644 --- a/proto/snmp/bgp_mib.c +++ b/proto/snmp/bgp_mib.c @@ -166,7 +166,7 @@ snmp_bgp_notify_backward_trans(struct snmp_proto *p, struct bgp_proto *bgp) void snmp_bgp_register(struct snmp_proto *p) { - snmp_log("snmp_bgp_register()"); + //snmp_log("snmp_bgp_register()"); //u32 bgp_mib_prefix[] = {1, 15, 1}; u32 bgp_mib_prefix[] = { 1, 15 }; @@ -568,7 +568,7 @@ oid_state_compare(const struct oid *oid, u8 state) static struct oid * update_bgp_oid(struct oid *oid, u8 state) { - snmp_log("update_bgp_oid()"); + //snmp_log("update_bgp_oid()"); if (state == BGP_INTERNAL_END || state == BGP_INTERNAL_INVALID || state == BGP_INTERNAL_NO_VALUE) return oid; @@ -589,7 +589,7 @@ update_bgp_oid(struct oid *oid, u8 state) return oid; } - snmp_log("update work"); + //snmp_log("update work"); switch (state) { case BGP_INTERNAL_BGP: @@ -730,7 +730,7 @@ bgp_find_dynamic_oid(struct snmp_proto *p, struct oid *o_start, const struct oid ASSUME(o_start != NULL); ASSUME(o_end != NULL); - snmp_log("bgp_find_dynamic_oid()"); + //snmp_log("bgp_find_dynamic_oid()"); ip4_addr ip4 = ip4_from_oid(o_start); ip4_addr dest; @@ -746,22 +746,22 @@ bgp_find_dynamic_oid(struct snmp_proto *p, struct oid *o_start, const struct oid ip4_from_u32(UINT32_MAX); } - snmp_log("ip addresses build (ip4) %I (dest) %I", ipa_from_ip4(ip4), ipa_from_ip4(dest)); + //snmp_log("ip addresses build (ip4) %I (dest) %I", ipa_from_ip4(ip4), ipa_from_ip4(dest)); net_addr net; net_fill_ip4(&net, ip4, IP4_MAX_PREFIX_LENGTH); - snmp_log("dynamic part of BGP mib"); + //snmp_log("dynamic part of BGP mib"); struct f_trie_walk_state ws; trie_walk_init(&ws, p->bgp_trie, NULL, 0); - snmp_log("walk init"); + //snmp_log("walk init"); if (trie_walk_next(&ws, &net)) { - snmp_log("trie_walk_next() returned true"); + //snmp_log("trie_walk_next() returned true"); /* * If the o_end is empty, then there are no conditions on the ip4 address. @@ -769,7 +769,7 @@ bgp_find_dynamic_oid(struct snmp_proto *p, struct oid *o_start, const struct oid int cmp = ip4_compare(net4_prefix(&net), dest); if (cmp < 0 || (cmp == 0 && snmp_is_oid_empty(o_end))) { - snmp_log("ip4_less() returned true"); + //snmp_log("ip4_less() returned true"); // TODO repair struct oid *o = snmp_oid_duplicate(p->pool, o_start); @@ -778,39 +778,37 @@ bgp_find_dynamic_oid(struct snmp_proto *p, struct oid *o_start, const struct oid return o; } else - snmp_log("ip4_less() returned false for %I >= %I", net4_prefix(&net), dest); + {}//snmp_log("ip4_less() returned false for %I >= %I", net4_prefix(&net), dest); } else - snmp_log("trie_walk_next() returned false, cleaning"); + {}//snmp_log("trie_walk_next() returned false, cleaning"); return NULL; } static struct oid * search_bgp_dynamic(struct snmp_proto *p, struct oid *o_start, struct oid *o_end, uint contid -UNUSED, u8 current_state) +UNUSED, u8 next_state) { - snmp_log("search_bgp_dynamic() dynamic part Yaaay!"); + //snmp_log("search_bgp_dynamic() dynamic part Yaaay!"); - /* TODO can be remove after implementing all BGP4-MIB::bgpPeerTable columns */ - u8 next_state = current_state; struct oid *o_copy = o_start; do { - snmp_log("do-while state %u", next_state); - snmp_oid_dump(o_start); + //snmp_log("do-while state %u", next_state); + //snmp_oid_dump(o_start); o_start = o_copy = update_bgp_oid(o_copy, next_state); o_start = bgp_find_dynamic_oid(p, o_start, o_end, next_state); - snmp_log("found"); - snmp_oid_dump(o_start); + //snmp_log("found"); + //snmp_oid_dump(o_start); next_state = snmp_bgp_next_state(next_state); /* The search in next state is done from beginning. */ o_start->ids[5] = o_start->ids[6] = o_start->ids[7] = o_start->ids[8] = 0; o_start->include = 1; - snmp_log("looping"); + //snmp_log("looping"); } while (o_start == NULL && next_state < BGP_INTERNAL_END); return o_start; @@ -835,7 +833,7 @@ snmp_bgp_find_next_oid(struct snmp_proto *p, struct oid *oid, uint UNUSED contid int match = trie_walk_init(&ws, p->bgp_trie, &net, 1); - snmp_log("match %d include %u", match, oid->include); + //snmp_log("match %d include %u", match, oid->include); if (match && oid->include) { oid->include = 0; @@ -845,14 +843,14 @@ snmp_bgp_find_next_oid(struct snmp_proto *p, struct oid *oid, uint UNUSED contid /* We skip the first match as we should not include ip address in oid */ if (match) { - snmp_log("continue"); + //snmp_log("continue"); trie_walk_next(&ws, &net); } if (trie_walk_next(&ws, &net)) { - snmp_oid_dump(oid); - snmp_log("setting up"); + //snmp_oid_dump(oid); + //snmp_log("setting up"); u32 res = ipa_to_u32(net_prefix(&net)); ASSUME(oid->n_subid == 9); @@ -863,7 +861,7 @@ snmp_bgp_find_next_oid(struct snmp_proto *p, struct oid *oid, uint UNUSED contid return 1; } - snmp_log("bad"); + //snmp_log("bad"); return 0; } @@ -871,26 +869,26 @@ static enum snmp_search_res snmp_bgp_search_dynamic(struct snmp_proto *p, struct oid **searched, const struct oid *o_end, uint UNUSED contid, u8 next_state) { struct oid *oid = *searched; - snmp_log(" **searched = 0x%p *oid = 0x%p", searched, oid); - snmp_oid_dump(*searched); - snmp_oid_dump(oid); + //snmp_log(" **searched = 0x%p *oid = 0x%p", searched, oid); + //snmp_oid_dump(*searched); + //snmp_oid_dump(oid); u8 end_state = MIN(snmp_bgp_state(o_end), BGP_INTERNAL_PEER_TABLE_END); - snmp_log("before assumption %s [%u] < %u INTERNAL_END", debug_bgp_states[end_state], end_state, BGP_INTERNAL_END); + //snmp_log("before assumption %s [%u] < %u INTERNAL_END", debug_bgp_states[end_state], end_state, BGP_INTERNAL_END); ASSUME(end_state <= BGP_INTERNAL_END); - snmp_log("before assupmtion oid 0x%p != NULL (0x0)", oid); + //snmp_log("before assupmtion oid 0x%p != NULL (0x0)", oid); ASSUME(oid != NULL); oid = update_bgp_oid(oid, next_state); - snmp_log("update bgp oid to state %s [%d]", debug_bgp_states[next_state], next_state); - snmp_oid_dump(*searched); - snmp_oid_dump(oid); + //snmp_log("update bgp oid to state %s [%d]", debug_bgp_states[next_state], next_state); + //snmp_oid_dump(*searched); + //snmp_oid_dump(oid); int found; while (!(found = snmp_bgp_find_next_oid(p, oid, contid)) && next_state <= end_state) { - snmp_log("loop"); + //snmp_log("loop"); next_state = snmp_bgp_next_state(next_state); if (next_state == BGP_INTERNAL_IDENTIFIER) @@ -915,7 +913,7 @@ snmp_bgp_search2(struct snmp_proto *p, struct oid **searched, const struct oid * enum snmp_search_res r = SNMP_SEARCH_END_OF_VIEW; u8 bgp_state = snmp_bgp_state(*searched); u8 state; - snmp_log("snmp_bgp_search2() with state %s [%d]", debug_bgp_states[bgp_state], bgp_state); + //snmp_log("snmp_bgp_search2() with state %s [%d]", debug_bgp_states[bgp_state], bgp_state); if (bgp_state == BGP_INTERNAL_END) { @@ -936,7 +934,7 @@ snmp_bgp_search2(struct snmp_proto *p, struct oid **searched, const struct oid * if (is_dynamic(state) && !is_dynamic(bgp_state)) { - snmp_log("searching a dynamic successor of static state"); + //snmp_log("searching a dynamic successor of static state"); for (uint i = 5; i < MIN(9, (*searched)->n_subid); i++) (*searched)->ids[i] = 0; r = snmp_bgp_search_dynamic(p, searched, o_end, contid, state); @@ -946,7 +944,7 @@ snmp_bgp_search2(struct snmp_proto *p, struct oid **searched, const struct oid * if (is_dynamic(bgp_state)) { - snmp_log("searching the dynamic states (peers)"); + //snmp_log("searching the dynamic states (peers)"); r = snmp_bgp_search_dynamic(p, searched, o_end, contid, bgp_state); if (r != SNMP_SEARCH_END_OF_VIEW) @@ -956,7 +954,7 @@ snmp_bgp_search2(struct snmp_proto *p, struct oid **searched, const struct oid * state = snmp_bgp_next_state(bgp_state); if (state <= BGP_INTERNAL_IDENTIFIER) { - snmp_log("returning the local identifier"); + //snmp_log("returning the local identifier"); *searched = update_bgp_oid(*searched, state); return SNMP_SEARCH_OK; } @@ -964,7 +962,7 @@ snmp_bgp_search2(struct snmp_proto *p, struct oid **searched, const struct oid * // TODO add route table /* end not found */ - snmp_log("reached unguarded code, returning END_OF_VIEW"); + //snmp_log("reached unguarded code, returning END_OF_VIEW"); return SNMP_SEARCH_END_OF_VIEW; } @@ -979,7 +977,7 @@ snmp_bgp_search(struct snmp_proto *p, struct oid *o_start, struct oid *o_end, ui if (o_start->include && snmp_bgp_has_value(start_state) && !is_dynamic(start_state) && o_start->n_subid == 3) { - snmp_log("snmp_bgp_search() first search element (due to include field) returned"); + //snmp_log("snmp_bgp_search() first search element (due to include field) returned"); /* We disable including for next time searching. */ o_start->include = 0; return o_start; @@ -987,7 +985,7 @@ snmp_bgp_search(struct snmp_proto *p, struct oid *o_start, struct oid *o_end, ui else if (o_start->include && snmp_bgp_has_value(start_state) && is_dynamic(start_state)) { - snmp_log("snmp_bgp_search() first search element matched dynamic entry!"); + //snmp_log("snmp_bgp_search() first search element matched dynamic entry!"); return search_bgp_dynamic(p, o_start, o_end, contid, start_state); } @@ -998,7 +996,7 @@ snmp_bgp_search(struct snmp_proto *p, struct oid *o_start, struct oid *o_end, ui if (!is_dynamic(next_state)) { o_start = update_bgp_oid(o_start, next_state); - snmp_log("next state is also not dynamic"); + //snmp_log("next state is also not dynamic"); return o_start; } @@ -1026,7 +1024,7 @@ bgp_fill_dynamic(struct snmp_proto UNUSED *p, struct agentx_varbind *vb, return pkt; } - snmp_log(" -> ip addr %I", addr); + //snmp_log(" -> ip addr %I", addr); // TODO XXX deal with possible change of (remote) ip; BGP should restart and // disappear struct snmp_bgp_peer *pe = HASH_FIND(p->bgp_hash, SNMP_HASH, addr); @@ -1040,7 +1038,7 @@ bgp_fill_dynamic(struct snmp_proto UNUSED *p, struct agentx_varbind *vb, ipa_equal(addr, ((struct bgp_proto *) proto)->remote_ip)) { bgp_proto = (struct bgp_proto *) proto; - snmp_log("bgp_dynamic_fill() using bgp_proto %p", bgp_proto); + //snmp_log("bgp_dynamic_fill() using bgp_proto %p", bgp_proto); } /* We did not found binded BGP protocol. */ else @@ -1223,12 +1221,13 @@ static byte * bgp_fill_static(struct snmp_proto *p, struct agentx_varbind *vb, byte *pkt, uint size UNUSED, uint contid UNUSED, int byte_ord UNUSED, u8 state) { - snmp_log("snmp bgp_fill_static ()\n"); - snmp_log("bgp_fill_static: vb->type %u, ptk %02x", vb->type, *((u32 *) pkt)); + ASSUME((void *) pkt == (void *) vb); + //snmp_log("snmp bgp_fill_static ()\n"); + //snmp_log("bgp_fill_static: vb->type %u, ptk %02x", vb->type, *((u32 *) pkt)); struct oid *oid = &vb->name; - snmp_oid_dump(oid); - snmp_log("bgp_fill_static"); + //snmp_oid_dump(oid); + //snmp_log("bgp_fill_static"); /* * snmp_bgp_state() check only prefix. To be sure on OID equivalence we need to @@ -1268,11 +1267,12 @@ UNUSED, uint contid UNUSED, int byte_ord UNUSED, u8 state) #if 0 snmp_log("bgp_fill_static: type %u packet %p", vb->type, pkt); - snmp_oid_dump(oid); + //snmp_oid_dump(oid); - snmp_log("snmp ended with non empty pkt %u starting from %p to %p\n", pkt - + /*snmp_log("snmp ended with non empty pkt %u starting from %p to %p\n", pkt - temp, temp, pkt); - snmp_dump_packet(temp, pkt - temp); +*/ + //snmp_dump_packet(temp, pkt - temp); #endif return pkt; } diff --git a/proto/snmp/config.Y b/proto/snmp/config.Y index db653f37..a61b536b 100644 --- a/proto/snmp/config.Y +++ b/proto/snmp/config.Y @@ -90,7 +90,7 @@ snmp_context: /* empty */ { if (!this_bond) { - log(L_INFO "snmp_context no string alloc"); + //log(L_INFO "snmp_context no string alloc"); this_bond = cfg_alloc(sizeof(struct snmp_bond)); } @@ -99,7 +99,7 @@ snmp_context: | CONTEXT DEFAULT { if (!this_bond) { - log(L_INFO "snmp_context CONTEXT DEFAULT alloc"); + //log(L_INFO "snmp_context CONTEXT DEFAULT alloc"); this_bond = cfg_alloc(sizeof(struct snmp_bond)); } this_bond->context = NULL; @@ -107,29 +107,30 @@ snmp_context: | CONTEXT text { if(!this_bond) { - log(L_INFO "snmp_context CONTEXT text alloc"); + //log(L_INFO "snmp_context CONTEXT text alloc"); this_bond = cfg_alloc(sizeof(struct snmp_bond)); } this_bond->context = $2; SNMP_CFG->contexts++; - log(L_INFO "storing context %s to bond at 0x%p", $2, this_bond); + //log(L_INFO "storing context %s to bond at 0x%p", $2, this_bond); } ; snmp_bgp_bond: BGP symbol snmp_context { /* the snmp_context rule sets the correct value of this_bond */ - log(L_INFO "this_bond (at 0x%p) has value %s", this_bond, + /*log(L_INFO "this_bond (at 0x%p) has value %s", this_bond, (this_bond->context) ? this_bond->context : ""); +*/ if (!this_bond) { - log(L_INFO "snmp_bgp_bond BGP symbol ... alloc"); + //log(L_INFO "snmp_bgp_bond BGP symbol ... alloc"); this_bond = cfg_alloc(sizeof(struct snmp_bond)); - log(L_INFO "Unexpedted alloc in snmp_bgp_bond rule"); + //log(L_INFO "Unexpedted alloc in snmp_bgp_bond rule"); } else { - log(L_INFO, "working with this_bond (at 0x%p)", this_bond); + //log(L_INFO, "working with this_bond (at 0x%p)", this_bond); } this_bond->type = SNMP_BGP; diff --git a/proto/snmp/snmp.c b/proto/snmp/snmp.c index 8f49997c..ec552828 100644 --- a/proto/snmp/snmp.c +++ b/proto/snmp/snmp.c @@ -106,14 +106,11 @@ snmp_init(struct proto_config *CF) p->bgp_local_as = cf->bgp_local_as; p->bgp_local_id = cf->bgp_local_id; - snmp_log("changing proto_snmp state to INIT"); + snmp_log("changing state to INIT"); p->state = SNMP_INIT; p->timeout = cf->timeout; - snmp_log("snmp_init() lip: %I:%u rip: %I:%u", - cf->local_ip, cf->local_port, cf->remote_ip, cf->remote_port); - /* used when assigning the context ids in s_cont_create() */ p->context_max = 1; p->context_id_map = NULL; @@ -179,7 +176,7 @@ void snmp_connected(sock *sk) { struct snmp_proto *p = sk->data; - snmp_log("snmp_connected() connection created"); + snmp_log("connection created"); p->state = SNMP_OPEN; @@ -203,9 +200,9 @@ snmp_reconnect(timer *tm) } static void -snmp_sock_err(sock *sk, int err) +snmp_sock_err(sock *sk, int UNUSED err) { - snmp_log("snmp_sock_err() %s - err no: %d", strerror(err), err); + snmp_log("socket error '%s' (errno: %d)", strerror(err), err); struct snmp_proto *p = sk->data; p->errs++; @@ -215,7 +212,7 @@ snmp_sock_err(sock *sk, int err) rfree(p->sock); p->sock = NULL; - snmp_log("changing proto_snmp state to LOCKED"); + snmp_log("changing state to LOCKED"); p->state = SNMP_LOCKED; p->startup_timer->hook = snmp_startup_timeout; @@ -226,7 +223,7 @@ snmp_sock_err(sock *sk, int err) static void snmp_start_locked(struct object_lock *lock) { - snmp_log("snmp_start_locked() - lock acquired; preparing socket"); + //snmp_log("snmp_start_locked() - lock acquired; preparing socket"); struct snmp_proto *p = lock->data; p->state = SNMP_LOCKED; @@ -256,6 +253,7 @@ snmp_start_locked(struct object_lock *lock) p->errs = 0; } + snmp_log("opening socket"); if (sk_open(s) < 0) { // TODO rather set the startup timer, then reset whole SNMP proto @@ -273,7 +271,6 @@ snmp_startup(struct snmp_proto *p) p->state != SNMP_LOCKED && p->state != SNMP_DOWN) { - snmp_log("startup() already in connected state %u", p->state); return; } @@ -283,11 +280,9 @@ snmp_startup(struct snmp_proto *p) return; } - snmp_log("snmp_startup(), praparing lock"); + snmp_log("preparing object lock"); p->state = SNMP_INIT; - /* Starting AgentX communicaiton channel. */ - struct object_lock *lock; lock = p->lock = olock_new(p->pool); @@ -299,13 +294,7 @@ snmp_startup(struct snmp_proto *p) lock->hook = snmp_start_locked; lock->data = p; - snmp_log("lock acquiring"); olock_acquire(lock); - - /* - snmp_log("local ip: %I:%u, remote ip: %I:%u", - p->local_ip, p->local_port, p->remote_ip, p->remote_port); - */ } /* this function is internal and shouldn't be used outside the snmp module */ @@ -343,7 +332,7 @@ snmp_ping_timeout(timer *tm) static int snmp_start(struct proto *P) { - snmp_log("snmp_start() - starting timer (almost)"); + //snmp_log("snmp_start() - starting timer (almost)"); struct snmp_proto *p = (void *) P; struct snmp_config *cf = (struct snmp_config *) P->cf; @@ -368,7 +357,7 @@ snmp_start(struct proto *P) /* We always have at least the default context */ p->context_id_map = mb_allocz(p->pool, cf->contexts * sizeof(struct snmp_context *)); - log(L_INFO "number of context allocated %d", cf->contexts); + //log(L_INFO "number of context allocated %d", cf->contexts); struct snmp_context *defaultc = mb_alloc(p->pool, sizeof(struct snmp_context)); defaultc->context = ""; @@ -401,14 +390,14 @@ snmp_start(struct proto *P) if (b->context) { const struct snmp_context *c = snmp_cont_create(p, b->context); - snmp_log("creating snmp context %s with id %u, writing", b->context, c->context_id); + //snmp_log("creating snmp context %s with id %u, writing", b->context, c->context_id); p->context_id_map[c->context_id] = c; peer->context_id = c->context_id; } } } - snmp_log("values of context cf %u proto %u", cf->contexts, p->context_max); + //snmp_log("values of context cf %u proto %u", cf->contexts, p->context_max); ASSUME(cf->contexts == p->context_max); snmp_startup(p); @@ -482,12 +471,14 @@ snmp_show_proto_info(struct proto *P) cli_msg(-1006, " remote ip: %I4", bcf->remote_ip); cli_msg(-1006, " local port: %I4", bcf->local_port); cli_msg(-1006, " remote port: %I4", bcf->remote_port); + /* if (conn) { cli_msg(-1006, " state: %u", conn->state); cli_msg(-1006, " remote as: %u", conn->remote_caps->as4_number); } */ + cli_msg(-1006, " in updates: %u", bp->stats.rx_updates); cli_msg(-1006, " out updates: %u", bp->stats.tx_updates); cli_msg(-1006, " in total: %u", bp->stats.rx_messages); @@ -532,7 +523,6 @@ snmp_postconfig(struct proto_config *CF) static int snmp_shutdown(struct proto *P) { - snmp_log("snmp_shutdown()"); struct snmp_proto *p = SKIP_BACK(struct snmp_proto, p, P); tm_stop(p->ping_timer); @@ -542,12 +532,10 @@ snmp_shutdown(struct proto *P) p->state == SNMP_CONN) { /* We have a connection established (at leased send out Open-PDU). */ + snmp_log("changing state to STOP"); p->state = SNMP_STOP; - p->startup_timer->hook = snmp_stop_timeout; - tm_set(p->startup_timer, current_time() + p->timeout S); - snmp_stop_subagent(p); return PS_STOP; diff --git a/proto/snmp/snmp.h b/proto/snmp/snmp.h index 6cfa9bb0..b75050ec 100644 --- a/proto/snmp/snmp.h +++ b/proto/snmp/snmp.h @@ -120,15 +120,15 @@ struct snmp_context { struct snmp_proto { struct proto p; struct object_lock *lock; - pool *pool; /* a shortcut to the procotol mem. pool */ - linpool *lp; + pool *pool; /* a shortcut to the procotol mem. pool */ + linpool *lp; /* linpool for bgp_trie nodes */ ip_addr local_ip; ip_addr remote_ip; u16 local_port; u16 remote_port; - ip_addr bgp_local_id; /* BGP4-MIB related fields */ + ip_addr bgp_local_id; /* BGP4-MIB related fields */ u32 bgp_local_as; sock *sock; diff --git a/proto/snmp/snmp_utils.c b/proto/snmp/snmp_utils.c index e658adc4..775bbbfd 100644 --- a/proto/snmp/snmp_utils.c +++ b/proto/snmp/snmp_utils.c @@ -33,8 +33,9 @@ snmp_is_oid_empty(const struct oid *oid) uint snmp_pkt_len(const byte *start, const byte *end) { - snmp_log("snmp_pkt_len start 0x%p end 0x%p res %u", start, end, (end - start) + /*snmp_log("snmp_pkt_len start 0x%p end 0x%p res %u", start, end, (end - start) - AGENTX_HEADER_SIZE); +*/ return (end - start) - AGENTX_HEADER_SIZE; } @@ -304,7 +305,7 @@ snmp_put_oid(byte *buf, struct oid *oid) byte * snmp_put_fbyte(byte *buf, u8 data) { - // log(L_INFO "paste_fbyte()"); + //log(L_INFO "paste_fbyte()"); put_u8(buf, data); put_u24(++buf, 0); // PADDING return buf + 3; @@ -320,7 +321,8 @@ snmp_oid_ip4_index(struct oid *o, uint start, ip4_addr addr) STORE_U32(o->ids[start + 3], temp & 0xFF); } -void snmp_oid_dump(const struct oid *oid) +void UNUSED +snmp_oid_dump(const struct oid *oid) { log(L_WARN "OID DUMP ========"); @@ -441,17 +443,19 @@ snmp_register_same(struct snmp_register *r, struct agentx_header *h, u8 class) void snmp_register_ack(struct snmp_proto *p, struct agentx_header *h, u8 class) { - snmp_log("snmp_register_ack()"); + //snmp_log("snmp_register_ack()"); - snmp_log("got sid: %u tid: %u pid: %u", h->session_id, h->transaction_id, + /*snmp_log("got sid: %u tid: %u pid: %u", h->session_id, h->transaction_id, h->packet_id); +*/ struct snmp_register *reg; WALK_LIST(reg, p->register_queue) { // TODO add support for more mib trees (other than BGP) - snmp_log("checking registration request sid: %u tid: %u pid: %u", + /*snmp_log("checking registration request sid: %u tid: %u pid: %u", reg->session_id, reg->transaction_id, reg->packet_id); +*/ if (snmp_register_same(reg, h, class)) { struct snmp_registered_oid *ro = \ @@ -467,16 +471,16 @@ h->packet_id); add_tail(&p->bgp_registered, &ro->n); - snmp_log(" register note find %u", list_length(&p->bgp_registered)); + //snmp_log(" register note find %u", list_length(&p->bgp_registered)); return; } } - snmp_log("unknown registration"); + //snmp_log("unknown registration"); } -void -snmp_dump_packet(byte *pkt, uint size) +void UNUSED +snmp_dump_packet(byte UNUSED *pkt, uint size) { snmp_log("dump"); for (uint i = 0; i < size; i += 4) @@ -519,13 +523,13 @@ snmp_varbind_type32(struct agentx_varbind *vb, uint size, enum agentx_type type, if (size < (uint) agentx_type_size(type)) { - snmp_log("varbind type32 returned NULL"); + //snmp_log("varbind type32 returned NULL"); return NULL; } vb->type = type; u32 *data = SNMP_VB_DATA(vb); - snmp_log("varbind type32 vb data 0x%p (from vb 0x%p)", data, (void *) vb); + //snmp_log("varbind type32 vb data 0x%p (from vb 0x%p)", data, (void *) vb); *data = val; return (byte *)(data + 1); } @@ -561,13 +565,14 @@ snmp_varbind_ip4(struct agentx_varbind *vb, uint size, ip4_addr addr) { if (size < snmp_str_size_from_len(4)) { - snmp_log("varbind ip4 NULL"); + //snmp_log("varbind ip4 NULL"); return NULL; } vb->type = AGENTX_IP_ADDRESS; - snmp_log("snmp_varbind_ip4 vb data 0x%p (from vb 0x%p)", SNMP_VB_DATA(vb), (void + /*snmp_log("snmp_varbind_ip4 vb data 0x%p (from vb 0x%p)", SNMP_VB_DATA(vb), (void *) vb); +*/ return snmp_put_ip4(SNMP_VB_DATA(vb), addr); } @@ -576,7 +581,7 @@ snmp_varbind_nstr(struct agentx_varbind *vb, uint size, const char *str, uint le { if (size < snmp_str_size_from_len(len)) { - snmp_log("varbind nstr NULL"); + //snmp_log("varbind nstr NULL"); return NULL; } diff --git a/proto/snmp/subagent.c b/proto/snmp/subagent.c index 739fdc20..43510dff 100644 --- a/proto/snmp/subagent.c +++ b/proto/snmp/subagent.c @@ -31,7 +31,6 @@ static void snmp_mib_fill2(struct snmp_proto *p, struct oid *oid, struct snmp_pd static uint parse_response(struct snmp_proto *p, byte *buf, uint size); static void do_response(struct snmp_proto *p, byte *buf, uint size); static uint parse_gets2_pdu(struct snmp_proto *p, byte *buf, uint size, uint *skip); -static uint parse_close_pdu(struct snmp_proto *p, byte *buf, uint size); static struct agentx_response *prepare_response(struct snmp_proto *p, struct snmp_pdu *c); static void response_err_ind(struct agentx_response *res, uint err, uint ind); static uint update_packet_size(struct snmp_proto *p, const byte *start, byte *end); @@ -86,15 +85,14 @@ open_pdu(struct snmp_proto *p, struct oid *oid) struct snmp_pdu c = SNMP_PDU_CONTEXT(sk); byte *buf = c.buffer; - /* +4 for timeout (1B with 4B alignment) */ - if (c.size < AGENTX_HEADER_SIZE + 4 + snmp_oid_size(oid) + +#define TIMEOUT_SIZE 4 /* 1B timeout, 3B zero padding */ + if (c.size < AGENTX_HEADER_SIZE + TIMEOUT_SIZE + snmp_oid_size(oid) + + snmp_str_size(cf->description)) { snmp_manage_tbuf(p, &c); buf = c.buffer; } - /* Function open_pdu() does not generate agentx_pkt. */ struct agentx_header *h = (struct agentx_header *) c.buffer; ADVANCE(c.buffer, c.size, AGENTX_HEADER_SIZE); SNMP_BLANK_HEADER(h, AGENTX_OPEN_PDU); @@ -117,6 +115,7 @@ open_pdu(struct snmp_proto *p, struct oid *oid) snmp_log("sk_send sleep"); else snmp_log("sk_send error"); +#undef TIMEOUT_SIZE } void @@ -209,7 +208,7 @@ de_allocate_pdu(struct snmp_proto *p, struct oid *oid, u8 type) if (size > AGENTX_HEADER_SIZE + ) { - snmp_log("de_allocate_pdu()"); + //snmp_log("de_allocate_pdu()"); struct agentx_header *h; SNMP_CREATE(pkt, struct agentx_header, h); @@ -222,7 +221,7 @@ de_allocate_pdu(struct snmp_proto *p, struct oid *oid, u8 type) } else - snmp_log("de_allocate_pdu(): insufficient size"); + {}//snmp_log("de_allocate_pdu(): insufficient size"); } */ @@ -247,12 +246,12 @@ un_register_pdu(struct snmp_proto *p, struct oid *oid, uint len, uint index, u8 if (c.size < sz) { - snmp_log("un_register_pdu() insufficient size"); + //snmp_log("un_register_pdu() insufficient size"); snmp_manage_tbuf(p, &c); buf = c.buffer; } - snmp_log("un_register_pdu()"); + //snmp_log("un_register_pdu()"); struct agentx_header *h = (struct agentx_header *) c.buffer; ADVANCE(c.buffer, c.size, AGENTX_HEADER_SIZE); @@ -261,9 +260,10 @@ un_register_pdu(struct snmp_proto *p, struct oid *oid, uint len, uint index, u8 SNMP_SESSION(h, p); c.byte_ord = h->flags & AGENTX_NETWORK_BYTE_ORDER; +/* log("un_register_pdu contid %u s_cont (at 0x%p) %s", contid, sc, (sc && sc->context) ? sc->context : ""); - +*/ SNMP_NON_DEFAULT_CONTEXT(h, c, contid); struct agentx_un_register_hdr *ur = (struct agentx_un_register_hdr *) c.buffer; @@ -288,7 +288,7 @@ un_register_pdu(struct snmp_proto *p, struct oid *oid, uint len, uint index, u8 uint s = update_packet_size(p, buf, c.buffer); - snmp_log("sending (un)register %s", snmp_pkt_type[type]); + //snmp_log("sending (un)register %s", snmp_pkt_type[type]); int ret = sk_send(sk, s); if (ret > 0) snmp_log("sk_send OK!"); @@ -319,8 +319,9 @@ close_pdu(struct snmp_proto *p, u8 reason) struct snmp_pdu c = SNMP_PDU_CONTEXT(sk); byte *buf = c.buffer; - snmp_log("close_pdu() size: %u %c %u", c.size, (c.size > AGENTX_HEADER_SIZE + 4) + /*snmp_log("close_pdu() size: %u %c %u", c.size, (c.size > AGENTX_HEADER_SIZE + 4) ? '>':'<', AGENTX_HEADER_SIZE); +*/ /* +4B for reason */ if (c.size < AGENTX_HEADER_SIZE + 4) @@ -341,7 +342,7 @@ close_pdu(struct snmp_proto *p, u8 reason) uint s = update_packet_size(p, buf, c.buffer); - snmp_log("preparing to sk_send() (close)"); + //snmp_log("preparing to sk_send() (close)"); int ret = sk_send(sk, s); if (ret > 0) snmp_log("sk_send OK!"); @@ -360,13 +361,13 @@ addagentcaps_pdu(struct snmp_proto *p, struct oid *cap, char *descr, sock *sk = p->sock; //byte *buf = sk->tbuf; //uint size = sk->tbsize; - // TODO rename to pkt and add pkt_start + // TO-DO rename to pkt and add pkt_start 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)) { - /* TODO need more mem */ + /* TO-DO need more mem */ return; } @@ -409,13 +410,13 @@ removeagentcaps_pdu(struct snmp_proto *p, struct oid *cap, struct agentx_context //byte *buf = sk->tbuf; //uint size = sk->tbsize; - // TODO rename to pkt and add pkt_start + // TO-DO rename to pkt and add pkt_start 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)) { - /* TODO need more mem */ + /* TO-DO need more mem */ return; } @@ -463,13 +464,12 @@ refresh_ids(struct snmp_proto *p, struct agentx_header *h) * @size: number of packet bytes in buffer * retval number of byte parsed * - * function parse_pkt() parses response-pdu and calls do_response(). - * returns number of bytes parsed by function excluding size of header. + * Returns number of bytes parsed from RX-buffer. */ static uint parse_pkt(struct snmp_proto *p, byte *pkt, uint size, uint *skip) { - snmp_log("parse_pkt() pkt start: %p", pkt); + //snmp_log("parse_pkt() pkt start: %p", pkt); if (size < AGENTX_HEADER_SIZE) return 0; @@ -477,13 +477,13 @@ parse_pkt(struct snmp_proto *p, byte *pkt, uint size, uint *skip) uint parsed_len = 0; struct agentx_header *h = (void *) pkt; - snmp_log("parse_pkt got type %s (%d)", snmp_pkt_type[h->type], h->type); - snmp_log("parse_pkt rx size %u", size); - snmp_dump_packet((void *)h, MIN(h->payload, 256)); + //snmp_log("parse_pkt got type %s (%d)", snmp_pkt_type[h->type], h->type); + //snmp_log("parse_pkt rx size %u", size); + //snmp_dump_packet((void *)h, MIN(h->payload, 256)); switch (h->type) { case AGENTX_RESPONSE_PDU: - snmp_log("parse_pkt returning parse_response"); + //snmp_log("parse_pkt returning parse_response"); parsed_len = parse_response(p, pkt, size); break; @@ -503,20 +503,20 @@ parse_pkt(struct snmp_proto *p, byte *pkt, uint size, uint *skip) break; */ - /* should not happen */ default: - snmp_log("unknown packet type %u", h->type); + /* drop the packet with unknown type silently */ + //snmp_log("unknown packet type %u", h->type); return 0; } - snmp_log("parse_pkt returning parsed length"); + //snmp_log("parse_pkt returning parsed length"); return parsed_len; } static uint parse_response(struct snmp_proto *p, byte *res, uint size) { - snmp_log("parse_response() g%u h%u", size, sizeof(struct agentx_header)); + //snmp_log("parse_response() g%u h%u", size, sizeof(struct agentx_header)); if (size < sizeof(struct agentx_response)) return 0; @@ -527,26 +527,29 @@ parse_response(struct snmp_proto *p, byte *res, uint size) int byte_ord = h->flags & AGENTX_NETWORK_BYTE_ORDER; uint pkt_size = LOAD_U32(h->payload, byte_ord); - snmp_log("p_res pkt_size %u", pkt_size); + //snmp_log("p_res pkt_size %u", pkt_size); if (size < pkt_size + AGENTX_HEADER_SIZE) { - snmp_log("parse_response early return"); + //snmp_log("parse_response early return"); return 0; } - snmp_log(" endianity: %s, session %u, transaction: %u", + /*snmp_log(" endianity: %s, session %u, transaction: %u", (h->flags & AGENTX_NETWORK_BYTE_ORDER) ? "big end": "little end", h->session_id, h->transaction_id); - snmp_log(" sid: %3u\ttid: %3u\tpid: %3u", p->session_id, p->transaction_id, +*/ + /*snmp_log(" sid: %3u\ttid: %3u\tpid: %3u", p->session_id, p->transaction_id, p->packet_id); +*/ + //snmp_log(" pkt size %u", h->payload); - snmp_log(" pkt size %u", h->payload); + //snmp_log(" pkt size %u", h->payload); if (r->error == AGENTX_RES_NO_ERROR) do_response(p, res, size); else /* erronous packet should be dropped quietly */ - snmp_log("an error occured '%s'", snmp_errs[get_u16(&r->error) - SNMP_ERR_SHIFT]); + {}//snmp_log("an error occured '%s'", snmp_errs[get_u16(&r->error) - SNMP_ERR_SHIFT]); return pkt_size + AGENTX_HEADER_SIZE; } @@ -554,17 +557,18 @@ parse_response(struct snmp_proto *p, byte *res, uint size) static void snmp_register_mibs(struct snmp_proto *p) { - snmp_log("snmp_register_mibs()"); + //snmp_log("snmp_register_mibs()"); snmp_bgp_register(p); + /* snmp_ospf_regsiter(p); ... */ - snmp_log("registering all done"); + //snmp_log("registering all done"); } static void do_response(struct snmp_proto *p, byte *buf, uint size) { - snmp_log("do_response()"); + //snmp_log("do_response()"); struct agentx_response *r = (void *) buf; struct agentx_header *h = &r->h; int byte_ord = h->flags & AGENTX_NETWORK_BYTE_ORDER; @@ -588,11 +592,11 @@ do_response(struct snmp_proto *p, byte *buf, uint size) snmp_log("changing state to REGISTER"); p->state = SNMP_REGISTER; snmp_register_mibs(p); - snmp_log("do_response state SNMP_INIT register list %u", list_length(&p->register_queue)); + //snmp_log("do_response state SNMP_INIT register list %u", list_length(&p->register_queue)); break; - case SNMP_REGISTER: - snmp_log("do_response state SNMP_REGISTER register list %u", list_length(&p->register_queue)); + case SNMP_REGISTER:; + //snmp_log("do_response state SNMP_REGISTER register list %u", list_length(&p->register_queue)); byte *pkt = buf; ADVANCE(pkt, size, AGENTX_HEADER_SIZE); @@ -611,7 +615,7 @@ do_response(struct snmp_proto *p, byte *buf, uint size) if (p->register_to_ack == 0) { - snmp_log("changing proto_snmp state to CONNECTED"); + snmp_log("changing state to CONNECTED"); p->state = SNMP_CONN; proto_notify_state(&p->p, PS_UP); } @@ -650,11 +654,11 @@ static int snmp_get_next2(struct snmp_proto *p, struct oid *o_start, struct oid *o_end, struct snmp_pdu *c) { - snmp_log("get_next2()"); + //snmp_log("get_next2()"); enum snmp_search_res r; - snmp_log("next2() o_end %p", o_end); + //snmp_log("next2() o_end %p", o_end); struct oid *o_copy = search_mib(p, o_start, o_end, NULL, c, &r); - snmp_log("next2()2 o_end %p", o_end); + //snmp_log("next2()2 o_end %p", o_end); struct agentx_varbind *vb = NULL; switch (r) @@ -774,9 +778,7 @@ snmp_get_bulk2(struct snmp_proto *p, struct oid *o_start, struct oid *o_end, static inline uint update_packet_size(struct snmp_proto *p, const byte *start, byte *end) { - /* work even for partial messages */ struct agentx_header *h = (void *) p->sock->tpos; - size_t s = snmp_pkt_len(start, end); STORE_U32(h->payload, s); return AGENTX_HEADER_SIZE + s; @@ -796,7 +798,7 @@ static uint parse_gets2_pdu(struct snmp_proto *p, byte * const pkt_start, uint size, uint *skip) { // TODO checks for c.size underflow - snmp_log("parse_gets2_pdu()"); + //snmp_log("parse_gets2_pdu()"); struct oid *o_start = NULL, *o_end = NULL; byte *pkt = pkt_start; @@ -822,7 +824,7 @@ parse_gets2_pdu(struct snmp_proto *p, byte * const pkt_start, uint size, uint *s */ if (size < clen) { - snmp_log("size %u < %u clen, returning 0", size, clen); + //snmp_log("size %u < %u clen, returning 0", size, clen); goto wait; } @@ -887,7 +889,7 @@ parse_gets2_pdu(struct snmp_proto *p, byte * const pkt_start, uint size, uint *s uint ind = 0; while (c.error == AGENTX_RES_NO_ERROR && size > 0 && pkt_size > 0) { - snmp_log("iter %u size %u remaining %u/%u", ind + 1, c.buffer - sk->tpos, size, pkt_size); + //snmp_log("iter %u size %u remaining %u/%u", ind + 1, c.buffer - sk->tpos, size, pkt_size); if (size < snmp_oid_sizeof(0)) goto partial; @@ -909,12 +911,12 @@ parse_gets2_pdu(struct snmp_proto *p, byte * const pkt_start, uint size, uint *s */ if (sz > size && ind > 0) { - snmp_log("sz %u > %u size && ind %u > 1", sz, size, ind + 1); + //snmp_log("sz %u > %u size && ind %u > 1", sz, size, ind + 1); goto partial; /* send already processed part */ } else if (sz > size) { - snmp_log("sz %u > %u size; returning 0", sz, size); + //snmp_log("sz %u > %u size; returning 0", sz, size); goto wait; } @@ -936,13 +938,13 @@ parse_gets2_pdu(struct snmp_proto *p, byte * const pkt_start, uint size, uint *s if (sz > size && ind > 0) { - snmp_log("sz2 %u > %u size && ind %u > 1", sz, size, ind + 1); + //snmp_log("sz2 %u > %u size && ind %u > 1", sz, size, ind + 1); size += snmp_oid_size(o_start_b); goto partial; } else if (sz > size) { - snmp_log("sz2 %u > %u size; returning 0", sz, size); + //snmp_log("sz2 %u > %u size; returning 0", sz, size); goto wait; } @@ -957,7 +959,7 @@ parse_gets2_pdu(struct snmp_proto *p, byte * const pkt_start, uint size, uint *s if (!snmp_is_oid_empty(o_end) && snmp_oid_compare(o_start, o_end) > 0) { - snmp_log("snmp_gets2() o_start does not preceed o_end, returning GEN_ERROR"); + //snmp_log("snmp_gets2() o_start does not preceed o_end, returning GEN_ERROR"); c.error = AGENTX_RES_GEN_ERROR; goto send; } @@ -1012,14 +1014,15 @@ parse_gets2_pdu(struct snmp_proto *p, byte * const pkt_start, uint size, uint *s } } -send: - snmp_log("gets2: sending response ..."); +send:; + //snmp_log("gets2: sending response ..."); struct agentx_response *res = (void *) sk->tbuf; /* We update the error, index pair on the beginning of the packet. */ response_err_ind(res, c.error, ind + 1); uint s = update_packet_size(p, (byte *) response_header, c.buffer); - snmp_log("sending response to Get-PDU, GetNext-PDU or GetBulk-PDU request (size %u)...", s); + //snmp_log("sending response to Get-PDU, GetNext-PDU or GetBulk-PDU request (size %u)...", s); + /* We send the message in TX-buffer. */ int ret = sk_send(sk, s); if (ret > 0) @@ -1040,13 +1043,13 @@ send: partial: - snmp_log("partial packet"); + //snmp_log("partial packet"); /* The context octet is not added into response pdu. */ /* need to tweak RX buffer packet size */ - snmp_log("old rx-buffer size %u", h->payload); + //snmp_log("old rx-buffer size %u", h->payload); (c.byte_ord) ? put_u32(&h->payload, pkt_size) : (h->payload = pkt_size); - snmp_log("new rx-buffer size %u", h->payload); + //snmp_log("new rx-buffer size %u", h->payload); *skip = AGENTX_HEADER_SIZE; p->partial_response = response_header; @@ -1065,8 +1068,8 @@ wait: void snmp_start_subagent(struct snmp_proto *p) { - snmp_log("snmp_start_subagent() starting subagent"); - snmp_log("DEBUG p->bgp_local_as %u", p->bgp_local_as); + //snmp_log("snmp_start_subagent() starting subagent"); + //snmp_log("DEBUG p->bgp_local_as %u", p->bgp_local_as); /* blank oid means unsupported */ struct oid *blank = snmp_oid_blank(p); @@ -1080,7 +1083,7 @@ snmp_start_subagent(struct snmp_proto *p) void snmp_stop_subagent(struct snmp_proto *p) { - snmp_log("snmp_stop_subagent() state %d", p->state); + //snmp_log("snmp_stop_subagent() state %d", p->state); if (p->state == SNMP_STOP) close_pdu(p, AGENTX_CLOSE_SHUTDOWN); @@ -1099,12 +1102,12 @@ oid_prefix(struct oid *o, u32 *prefix, uint len) int snmp_rx(sock *sk, uint size) { - snmp_log("snmp_rx() size %u", size); + //snmp_log("snmp_rx() size %u", size); //snmp_dump_packet(sk->tbuf, 64); struct snmp_proto *p = sk->data; byte *pkt_start = sk->rbuf; byte *end = pkt_start + size; - snmp_log("snmp_rx rbuf 0x%p rpos 0x%p", sk->rbuf, sk->rpos); + //snmp_log("snmp_rx rbuf 0x%p rpos 0x%p", sk->rbuf, sk->rpos); /* * In some cases we want to save the header for future parsing, skip is number @@ -1112,14 +1115,15 @@ snmp_rx(sock *sk, uint size) */ uint skip = 0; - snmp_log("snmp_rx before loop"); + //snmp_log("snmp_rx before loop"); while (end >= pkt_start + AGENTX_HEADER_SIZE && skip == 0) { uint parsed_len = parse_pkt(p, pkt_start, size, &skip); - snmp_log("snmp_rx loop end %p parsed >>> %u <<< curr %p", end, parsed_len, + /*snmp_log("snmp_rx loop end %p parsed >>> %u <<< curr %p", end, parsed_len, pkt_start + parsed_len); - snmp_log("snmp_rx loop2 rpos 0x%p", sk->rpos); +*/ + //snmp_log("snmp_rx loop2 rpos 0x%p", sk->rpos); if (parsed_len == 0) break; @@ -1127,23 +1131,23 @@ snmp_rx(sock *sk, uint size) pkt_start += parsed_len; size -= parsed_len; } - snmp_log("snmp_rx loop finished"); + //snmp_log("snmp_rx loop finished"); /* Incomplete packets */ if (skip != 0 || pkt_start != end) { - snmp_log("snmp_rx memmove"); - snmp_dump_packet(sk->rbuf, SNMP_RX_BUFFER_SIZE); + //snmp_log("snmp_rx memmove"); + //snmp_dump_packet(sk->rbuf, SNMP_RX_BUFFER_SIZE); memmove(sk->rbuf + skip, pkt_start, size); - snmp_log("after change; sk->rbuf 0x%p sk->rpos 0x%p", sk->rbuf, sk->rpos); - snmp_dump_packet(sk->rbuf, size + skip); - snmp_log("tweaking rpos 0x%p (size %u skip %u)", sk->rpos, size, skip); + //snmp_log("after change; sk->rbuf 0x%p sk->rpos 0x%p", sk->rbuf, sk->rpos); + //snmp_dump_packet(sk->rbuf, size + skip); + //snmp_log("tweaking rpos 0x%p (size %u skip %u)", sk->rpos, size, skip); sk->rpos = sk->rbuf + size + skip; - snmp_log("snmp_rx returing 0"); + //snmp_log("snmp_rx returing 0"); return 0; } - snmp_log("snmp_rx returning 1"); + //snmp_log("snmp_rx returning 1"); return 1; } @@ -1152,14 +1156,14 @@ void snmp_ping(struct snmp_proto *p) { sock *sk = p->sock; - snmp_dump_packet(sk->tpos, AGENTX_HEADER_SIZE + 4); - snmp_log("snmp_ping sk->tpos 0x%p", sk->tpos); + //snmp_dump_packet(sk->tpos, AGENTX_HEADER_SIZE + 4); + //snmp_log("snmp_ping sk->tpos 0x%p", sk->tpos); struct snmp_pdu c = SNMP_PDU_CONTEXT(sk); if (c.size < AGENTX_HEADER_SIZE) snmp_manage_tbuf(p, &c); - snmp_log("ping_pdu()"); + //snmp_log("ping_pdu()"); struct agentx_header *h = (struct agentx_header *) c.buffer; ADVANCE(c.buffer, c.size, AGENTX_HEADER_SIZE); SNMP_BLANK_HEADER(h, AGENTX_PING_PDU); @@ -1167,8 +1171,8 @@ snmp_ping(struct snmp_proto *p) SNMP_SESSION(h, p); c.byte_ord = AGENTX_NETWORK_BYTE_ORDER; - snmp_log("sending ping packet ... tpos 0x%p", sk->tpos); - snmp_dump_packet(sk->tpos, AGENTX_HEADER_SIZE + 4); + //snmp_log("sending ping packet ... tpos 0x%p", sk->tpos); + //snmp_dump_packet(sk->tpos, AGENTX_HEADER_SIZE + 4); /* sending only header -> pkt - buf */ uint s = update_packet_size(p, sk->tpos, c.buffer); @@ -1210,8 +1214,9 @@ has_inet_prefix(struct oid *o) */ int snmp_search_check_end_oid(const struct oid *found, const struct oid *bound) { - snmp_log("upper_bound_check(*f, *b) %p %p is_empty() %d", found, bound, + /*snmp_log("upper_bound_check(*f, *b) %p %p is_empty() %d", found, bound, snmp_is_oid_empty(bound)); +*/ if (snmp_is_oid_empty(bound)) return 1; @@ -1226,7 +1231,7 @@ search_mib(struct snmp_proto *p, const struct oid *o_start, const struct oid *o_ struct oid *o_curr, struct snmp_pdu *c, enum snmp_search_res *result) { - snmp_log("search_mib()"); + //snmp_log("search_mib()"); ASSUME(o_start != NULL); if (o_curr && (o_curr->n_subid < 2 || o_curr->ids[0] != 1)) @@ -1246,7 +1251,7 @@ search_mib(struct snmp_proto *p, const struct oid *o_start, const struct oid *o_ snmp_get_mib_class(o_curr) < snmp_get_mib_class(o_end)) { o_end = blank = snmp_oid_blank(p); - snmp_log("search_mib() o_end points to blank oid now %p", o_end); + //snmp_log("search_mib() o_end points to blank oid now %p", o_end); } enum snmp_search_res r; @@ -1293,32 +1298,35 @@ struct oid * snmp_prefixize(struct snmp_proto *proto, const struct oid *oid, int byte_ord) { ASSERT(oid != NULL); - snmp_log("snmp_prefixize()"); + //snmp_log("snmp_prefixize()"); if (snmp_is_oid_empty(oid)) { /* allocate new zeroed oid */ - snmp_log("blank"); + //snmp_log("blank"); return snmp_oid_blank(proto); } /* already in prefixed form */ else if (oid->prefix != 0) { struct oid *new = snmp_oid_duplicate(proto->pool, oid); - snmp_log("already prefixed"); + //snmp_log("already prefixed"); return new; } if (oid->n_subid < 5) - { snmp_log("too small"); return NULL; } + return NULL; + //{ snmp_log("too small"); return NULL; } for (int i = 0; i < 4; i++) if (LOAD_U32(oid->ids[i], byte_ord) != snmp_internet[i]) - { snmp_log("different prefix"); return NULL; } + return NULL; + //{ snmp_log("different prefix"); return NULL; } /* validity check here */ if (oid->ids[4] >= 256) - { snmp_log("outside byte first id"); return NULL; } + return NULL; + //{ snmp_log("outside byte first id"); return NULL; } struct oid *new = mb_alloc(proto->pool, sizeof(struct oid) + MAX((oid->n_subid - 5) * sizeof(u32), 0)); @@ -1362,6 +1370,7 @@ snmp_mib_fill2(struct snmp_proto *p, struct oid *oid, case SNMP_CLASS_INVALID: case SNMP_CLASS_END: default: + break; vb->type = AGENTX_NO_SUCH_OBJECT; ADVANCE(c->buffer, c->size, snmp_varbind_header_size(vb)); } @@ -1375,26 +1384,17 @@ snmp_mib_fill2(struct snmp_proto *p, struct oid *oid, void snmp_manage_tbuf(struct snmp_proto UNUSED *p, struct snmp_pdu *c) { - snmp_log("snmp_manage_tbuf()"); + //snmp_log("snmp_manage_tbuf()"); sock *sk = p->sock; sk_set_tbsize(sk, sk->tbsize + 2048); c->size += 2048; } -/* -void -snmp_tx(sock UNUSED *sk) -{ - snmp_log("snmp_tx"); -} -*/ - - static struct agentx_response * prepare_response(struct snmp_proto *p, struct snmp_pdu *c) { - snmp_log("prepare_response()"); + //snmp_log("prepare_response()"); if (!p->partial_response) { diff --git a/proto/snmp/subagent.h b/proto/snmp/subagent.h index a4be3b8b..dac6f7f9 100644 --- a/proto/snmp/subagent.h +++ b/proto/snmp/subagent.h @@ -115,7 +115,7 @@ enum snmp_search_res { #define COPY_STR(proto, buf, str, length, byte_order) ({ \ length = LOAD_PTR(buf, byte_order); \ - log(L_INFO "LOAD_STR(), %p %u", proto->pool, length + 1); \ + /*log(L_INFO "LOAD_STR(), %p %u", proto->pool, length + 1); */ \ str = mb_alloc(proto->pool, length + 1); \ memcpy(str, buf+4, length); \ str[length] = '\0'; /* set term. char */ \ @@ -338,6 +338,10 @@ u8 snmp_get_mib_class(const struct oid *oid); // debug wrapper +#if 0 #define snmp_log(...) log(L_INFO "snmp " __VA_ARGS__) +#else +#define snmp_log(...) do { } while(0) +#endif #endif From f2f9810b861860c49f84ac843edab790eddc3b3a Mon Sep 17 00:00:00 2001 From: Vojtech Vilimek Date: Thu, 19 Oct 2023 16:03:22 +0200 Subject: [PATCH 2/5] fixup! An unexpected NULL pilgrim --- proto/snmp/snmp.c | 1 - 1 file changed, 1 deletion(-) diff --git a/proto/snmp/snmp.c b/proto/snmp/snmp.c index ec552828..e0e5e59c 100644 --- a/proto/snmp/snmp.c +++ b/proto/snmp/snmp.c @@ -366,7 +366,6 @@ snmp_start(struct proto *P) HASH_INSERT(p->context_hash, SNMP_H_CONTEXT, defaultc); p->context_id_map[0] = defaultc; - p->bgp_trie = NULL; struct snmp_bond *b; WALK_LIST(b, cf->bgp_entries) From 6c59bcdfbb2098621400952f8500d83ce51bb3a2 Mon Sep 17 00:00:00 2001 From: Vojtech Vilimek Date: Thu, 19 Oct 2023 16:08:13 +0200 Subject: [PATCH 3/5] SNMP: Remove old code --- proto/snmp/snmp.c | 3 --- proto/snmp/snmp.h | 6 ------ proto/snmp/subagent.c | 30 +++++++++++------------------- 3 files changed, 11 insertions(+), 28 deletions(-) diff --git a/proto/snmp/snmp.c b/proto/snmp/snmp.c index e0e5e59c..bde36779 100644 --- a/proto/snmp/snmp.c +++ b/proto/snmp/snmp.c @@ -134,8 +134,6 @@ snmp_cleanup(struct snmp_proto *p) rfree(p->lock); p->lock = NULL; - p->partial_response = NULL; - struct snmp_register *r, *r2; WALK_LIST_DELSAFE(r, r2, p->register_queue) { @@ -338,7 +336,6 @@ snmp_start(struct proto *P) p->to_send = 0; p->errs = 0; - p->partial_response = NULL; p->startup_timer = tm_new_init(p->pool, snmp_startup_timeout, p, 0, 0); p->ping_timer = tm_new_init(p->pool, snmp_ping_timeout, p, 0, 0); diff --git a/proto/snmp/snmp.h b/proto/snmp/snmp.h index b75050ec..34c4e7d6 100644 --- a/proto/snmp/snmp.h +++ b/proto/snmp/snmp.h @@ -161,12 +161,6 @@ struct snmp_proto { uint to_send; uint errs; - - /* - * if the packet hasn't been fully recieved, partial_reponse points - * into the TX buffer to the Response-PDU header (needed for packet payload) - */ - struct agentx_response *partial_response; }; //void snmp_tx(sock *sk); diff --git a/proto/snmp/subagent.c b/proto/snmp/subagent.c index 43510dff..47ec574d 100644 --- a/proto/snmp/subagent.c +++ b/proto/snmp/subagent.c @@ -878,7 +878,7 @@ parse_gets2_pdu(struct snmp_proto *p, byte * const pkt_start, uint size, uint *s }; } - if (!p->partial_response && c.size < sizeof(struct agentx_response)) + if (c.size < sizeof(struct agentx_response)) { snmp_manage_tbuf(p, &c); // TODO renew pkt, pkt_start pointers context clen @@ -1033,8 +1033,6 @@ send:; snmp_log("sk_send error"); // TODO think through the error state - p->partial_response = NULL; - mb_free(o_start); mb_free(o_end); @@ -1051,7 +1049,6 @@ partial: (c.byte_ord) ? put_u32(&h->payload, pkt_size) : (h->payload = pkt_size); //snmp_log("new rx-buffer size %u", h->payload); *skip = AGENTX_HEADER_SIZE; - p->partial_response = response_header; /* number of bytes parsed from RX-buffer */ return pkt - pkt_start; @@ -1396,24 +1393,19 @@ prepare_response(struct snmp_proto *p, struct snmp_pdu *c) { //snmp_log("prepare_response()"); - if (!p->partial_response) - { - struct agentx_response *r = (void *) c->buffer; - struct agentx_header *h = &r->h; + struct agentx_response *r = (void *) c->buffer; + struct agentx_header *h = &r->h; - SNMP_BLANK_HEADER(h, AGENTX_RESPONSE_PDU); - SNMP_SESSION(h, p); + SNMP_BLANK_HEADER(h, AGENTX_RESPONSE_PDU); + SNMP_SESSION(h, p); - /* protocol doesn't care about subagent upTime */ - STORE_U32(r->uptime, 0); - STORE_U16(r->error, AGENTX_RES_NO_ERROR); - STORE_U16(r->index, 0); + /* protocol doesn't care about subagent upTime */ + STORE_U32(r->uptime, 0); + STORE_U16(r->error, AGENTX_RES_NO_ERROR); + STORE_U16(r->index, 0); - ADVANCE(c->buffer, c->size, sizeof(struct agentx_response)); - return r; - } - - return p->partial_response; + ADVANCE(c->buffer, c->size, sizeof(struct agentx_response)); + return r; } From faa62625739a98f0c20e63bb6e7b2b1fbc43bfaa Mon Sep 17 00:00:00 2001 From: Vojtech Vilimek Date: Thu, 19 Oct 2023 16:20:37 +0200 Subject: [PATCH 4/5] SNMP: Code improvements --- proto/snmp/snmp.c | 13 ++------ proto/snmp/subagent.c | 69 +++++++------------------------------------ proto/snmp/subagent.h | 2 +- 3 files changed, 14 insertions(+), 70 deletions(-) diff --git a/proto/snmp/snmp.c b/proto/snmp/snmp.c index bde36779..6c5ed239 100644 --- a/proto/snmp/snmp.c +++ b/proto/snmp/snmp.c @@ -252,13 +252,9 @@ snmp_start_locked(struct object_lock *lock) } snmp_log("opening socket"); + /* Try opening the socket, schedule a retry on fail */ if (sk_open(s) < 0) - { - // TODO rather set the startup timer, then reset whole SNMP proto - log(L_ERR "Cannot open listening socket"); - snmp_down(p); - // TODO go back to SNMP_INIT and try reconnecting after timeout - } + tm_set(p->startup_timer, current_time() + p->timeout S); } /* this function is internal and shouldn't be used outside the snmp module */ @@ -307,10 +303,7 @@ static void snmp_stop_timeout(timer *t) { snmp_log("stop timer triggered"); - - struct snmp_proto *p = t->data; - - snmp_down(p); + snmp_down(t->data); } static void diff --git a/proto/snmp/subagent.c b/proto/snmp/subagent.c index 47ec574d..1ace2c43 100644 --- a/proto/snmp/subagent.c +++ b/proto/snmp/subagent.c @@ -38,7 +38,7 @@ static struct oid *search_mib(struct snmp_proto *p, const struct oid *o_start, c u32 snmp_internet[] = { SNMP_ISO, SNMP_ORG, SNMP_DOD, SNMP_INTERNET }; -static const char * const snmp_errs[] = { +static const char * const snmp_errs[] UNUSED = { #define SNMP_ERR_SHIFT 256 [AGENTX_RES_OPEN_FAILED - SNMP_ERR_SHIFT] = "Open failed", [AGENTX_RES_NOT_OPEN - SNMP_ERR_SHIFT] = "Not open", @@ -55,7 +55,7 @@ static const char * const snmp_errs[] = { [AGENTX_RES_PROCESSING_ERR - SNMP_ERR_SHIFT] = "Processing error", }; -static const char * const snmp_pkt_type[] = { +static const char * const snmp_pkt_type[] UNUSED = { [AGENTX_OPEN_PDU] = "Open-PDU", [AGENTX_CLOSE_PDU] = "Close-PDU", [AGENTX_REGISTER_PDU] = "Register-PDU", @@ -108,13 +108,7 @@ open_pdu(struct snmp_proto *p, struct oid *oid) c.buffer = snmp_put_str(c.buffer, cf->description); uint s = update_packet_size(p, buf, c.buffer); - int ret = sk_send(sk, s); - if (ret > 0) - snmp_log("sk_send OK!"); - else if (ret == 0) - snmp_log("sk_send sleep"); - else - snmp_log("sk_send error"); + sk_send(sk, s); #undef TIMEOUT_SIZE } @@ -184,13 +178,7 @@ snmp_notify_pdu(struct snmp_proto *p, struct oid *oid, void *data, uint size, in ADVANCE(c.buffer, c.size, size); uint s = update_packet_size(p, sk->tbuf, c.buffer); - int ret = sk_send(sk, s); - if (ret > 0) - snmp_log("sk_send OK!"); - else if (ret == 0) - snmp_log("sk_send sleep"); - else - snmp_log("sk_send error"); + sk_send(sk, s); #undef TRAP0_HEADER_SIZE #undef UPTIME_SIZE @@ -289,13 +277,7 @@ un_register_pdu(struct snmp_proto *p, struct oid *oid, uint len, uint index, u8 uint s = update_packet_size(p, buf, c.buffer); //snmp_log("sending (un)register %s", snmp_pkt_type[type]); - int ret = sk_send(sk, s); - if (ret > 0) - snmp_log("sk_send OK!"); - else if (ret == 0) - snmp_log("sk_send sleep"); - else - snmp_log("sk_send error"); + sk_send(sk, s); } /* Register-PDU */ @@ -343,13 +325,7 @@ close_pdu(struct snmp_proto *p, u8 reason) uint s = update_packet_size(p, buf, c.buffer); //snmp_log("preparing to sk_send() (close)"); - int ret = sk_send(sk, s); - if (ret > 0) - snmp_log("sk_send OK!"); - else if (ret == 0) - snmp_log("sk_send sleep"); - else - snmp_log("sk_send error"); + sk_send(sk, s); } #if 0 @@ -394,13 +370,7 @@ addagentcaps_pdu(struct snmp_proto *p, struct oid *cap, char *descr, // make a note in the snmp_proto structure //int ret = sk_send(sk, buf - sk->tbuf); - int ret = sk_send(sk, buf - sk->tpos); - if (ret == 0) - snmp_log("sk_send sleep"); - else if (ret < 0) - snmp_log("sk_send err"); - else - log(L_INFO, "sk_send ok !!"); + sk_send(sk, buf - sk->tpos); } static void UNUSED @@ -438,14 +408,7 @@ removeagentcaps_pdu(struct snmp_proto *p, struct oid *cap, struct agentx_context // update state in snmp_proto structure - //int ret = sk_send(sk, buf - sk->tbuf); - int ret = sk_send(sk, buf - sk->tpos); - if (ret == 0) - snmp_log("sk_send sleep"); - else if (ret < 0) - snmp_log("sk_send err"); - else - log(L_INFO, "sk_send ok !!"); + sk_send(sk, buf - sk->tpos); } #endif @@ -1024,13 +987,7 @@ send:; //snmp_log("sending response to Get-PDU, GetNext-PDU or GetBulk-PDU request (size %u)...", s); /* We send the message in TX-buffer. */ - int ret = sk_send(sk, s); - if (ret > 0) - snmp_log("sk_send OK!"); - else if (ret == 0) - snmp_log("sk_send sleep"); - else - snmp_log("sk_send error"); + sk_send(sk, s); // TODO think through the error state mb_free(o_start); @@ -1173,13 +1130,7 @@ snmp_ping(struct snmp_proto *p) /* sending only header -> pkt - buf */ uint s = update_packet_size(p, sk->tpos, c.buffer); - int ret = sk_send(sk, s); - if (ret > 0) - snmp_log("sk_send OK!"); - else if (ret == 0) - snmp_log("sk_send sleep"); - else - snmp_log("sk_send error"); + sk_send(sk, s); } static inline int diff --git a/proto/snmp/subagent.h b/proto/snmp/subagent.h index dac6f7f9..937b2de9 100644 --- a/proto/snmp/subagent.h +++ b/proto/snmp/subagent.h @@ -122,7 +122,7 @@ enum snmp_search_res { buf += 4 + snmp_str_size_from_len(length); }) #define SNMP_LOAD_CONTEXT(hdr, buf, cont, cont_len) ({ \ - if ((hdr)->flags & AGENTX_NON_DEFAULT_CONTEXT) \ + if (cont = NULL, cont_len = 0, (hdr)->flags & AGENTX_NON_DEFAULT_CONTEXT) \ LOAD_STR((buf), (cont), (cont_len), \ (hdr)->flags & AGENTX_NETWORK_BYTE_ORDER); }) From e15f38e082df00ea7fcb7246b712fa0aacbb8481 Mon Sep 17 00:00:00 2001 From: Vojtech Vilimek Date: Thu, 19 Oct 2023 16:27:04 +0200 Subject: [PATCH 5/5] SNMP: Bare support for agentx-TestSet-PDU --- proto/snmp/bgp_mib.c | 9 ++ proto/snmp/bgp_mib.h | 1 + proto/snmp/subagent.c | 348 +++++++++++++++++++++++++++++++++++++++--- proto/snmp/subagent.h | 4 +- 4 files changed, 342 insertions(+), 20 deletions(-) diff --git a/proto/snmp/bgp_mib.c b/proto/snmp/bgp_mib.c index 59fb7524..64782cdc 100644 --- a/proto/snmp/bgp_mib.c +++ b/proto/snmp/bgp_mib.c @@ -1302,3 +1302,12 @@ snmp_bgp_fill(struct snmp_proto *p, struct agentx_varbind *vb, ADVANCE(c->buffer, c->size, snmp_varbind_header_size(vb)); } +#if 0 +int +snmp_bgp_testset(struct snmp_proto *p, const struct agentx_varbind *vb, void *tr, struct oid *oid, uint pkt_size) +{ + // TODO: check the type of varbind vb and it's value correctness, don't overflow the pkt_size + return 0; +} +#endif + diff --git a/proto/snmp/bgp_mib.h b/proto/snmp/bgp_mib.h index 3d6f07ee..b07d3c92 100644 --- a/proto/snmp/bgp_mib.h +++ b/proto/snmp/bgp_mib.h @@ -46,6 +46,7 @@ u8 snmp_bgp_getnext_valid(u8 state); struct oid *snmp_bgp_search(struct snmp_proto *p, struct oid *o_start, struct oid *o_end, uint contid); 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 *c); +//int snmp_bgp_testset(struct snmp_proto *p, const struct agentx_varbind *vb, void* tr, struct oid *oid, uint pkt_type); 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); diff --git a/proto/snmp/subagent.c b/proto/snmp/subagent.c index 1ace2c43..47232b35 100644 --- a/proto/snmp/subagent.c +++ b/proto/snmp/subagent.c @@ -328,6 +328,59 @@ close_pdu(struct snmp_proto *p, u8 reason) sk_send(sk, s); } +static uint UNUSED +parse_close_pdu(struct snmp_proto UNUSED *p, byte UNUSED *req, uint UNUSED size) +{ + /* + snmp_log("parse_close_pdu()"); + + // byte *pkt = req; + // sock *sk = p->sock; + + if (size < sizeof(struct agentx_header)) + { + snmp_log("p_close early return"); + return 0; + } + + // struct agentx_header *h = (void *) req; + ADVANCE(req, size, AGENTX_HEADER_SIZE); + //snmp_log("after header %p", req); + + p->state = SNMP_ERR; + + // or snmp_cleanup(); // ??! + proto_notify_state(&p->p, PS_DOWN); + */ + return 0; +} + +/* MUCH better signature would be + static int snmp_testset(struct snmp_proto *p, const struct agentx_varbind *vb, uint pkt_size); + */ +/* return 1 if the value could be set */ +static int +snmp_testset(struct snmp_proto *p, const struct agentx_varbind *vb, struct oid *oid, uint pkt_size) +{ + /* Hard-coded no support for writing */ + (void)p;(void)vb;(void)oid;(void)pkt_size; + return 0; +#if 0 + // TODO better logic + if (!oid) + return 0; + + switch (oid->ids[1]) + { + case SNMP_BGP4_MIB: + return snmp_bgp_testset(p, vb, oid, pkt_size); + default: + return 0; + } +#endif +} + + #if 0 static void UNUSED addagentcaps_pdu(struct snmp_proto *p, struct oid *cap, char *descr, @@ -420,6 +473,194 @@ refresh_ids(struct snmp_proto *p, struct agentx_header *h) p->packet_id = LOAD_U32(h->packet_id, byte_ord); } +static uint +parse_test_set_pdu(struct snmp_proto *p, byte *pkt, uint size) +{ + //snmp_log("parse_test_set"); + const byte *pkt_start = pkt; /* start of packet in RX-buffer */ + uint ind = 0; /* index of the error */ + uint s; /* final packat size */ + struct agentx_response *res; /* pointer to reponse in TX-buffer */ + + struct agentx_header *h = (void *) pkt; + ADVANCE(pkt, size, AGENTX_HEADER_SIZE); + uint pkt_size = LOAD_U32(h->payload, h->flags & AGENTX_NETWORK_BYTE_ORDER); + + sock *sk = p->sock; + struct snmp_pdu c = SNMP_PDU_CONTEXT(sk); + byte *buf = c.buffer; /* start of packet in TX-buffer */ + c.byte_ord = 0; /* use little-endian */ + + if (c.size < AGENTX_HEADER_SIZE) + { + snmp_manage_tbuf(p, &c); + // TODO renew all pointers + } + + 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; + + //snmp_log("test_set: parsed header and context"); + /* 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(...); + void *tr = mb_alloc(p->pool, 16); + + struct agentx_varbind *vb; + uint sz; + while (size > 0 && all_possible) + { + vb = (void *) pkt; + sz = snmp_varbind_size(vb, 0); + + if (sz > size) + /* wait for more data to arive */ + return 0; + + if (sz > pkt_size) + { + c.error = AGENTX_RES_PARSE_ERROR; + goto error; + } + + /* Unknown VarBind type check */ + if (!snmp_test_varbind(vb)) + { + c.error = AGENTX_RES_PARSE_ERROR; + goto error; + } + ADVANCE(pkt, size, snmp_varbind_size(vb, 0)); + + // TODO remove the mb_alloc() in prefixize() + struct oid *work = snmp_prefixize(p, &vb->name, c.byte_ord); + (void)work; + all_possible = snmp_testset(p, vb, tr, work, pkt_size); + mb_free(work); + } + //snmp_log("test_set parsed all varbinds"); + mb_free(tr); +#endif + +error: + s = update_packet_size(p, buf, c.buffer); + + if (c.error != AGENTX_RES_NO_ERROR) + response_err_ind(res, c.error, ind + 1); + else if (all_possible) + response_err_ind(res, AGENTX_RES_NO_ERROR, 0); + else + //response_err_ind(res, AGENTX_RES_RESOURCE_UNAVAILABLE, ind + 1); + response_err_ind(res, AGENTX_RES_NOT_WRITABLE, ind + 1); + + //snmp_log("test_set sending response"); + sk_send(sk, s); + return pkt - pkt_start; +} + +static uint +parse_set_pdu(struct snmp_proto *p, byte *pkt, uint size, uint err) +{ + const byte *pkt_start = pkt; + + if (size < AGENTX_HEADER_SIZE) + return 0; + + struct agentx_header *h = (void *) pkt; + ADVANCE(pkt, size, AGENTX_HEADER_SIZE); + uint pkt_size = LOAD_U32(h->payload, h->flags & AGENTX_NETWORK_BYTE_ORDER); + + struct snmp_pdu c = SNMP_PDU_CONTEXT(p->sock); + if (c.size < sizeof(struct agentx_response)) + { + snmp_manage_tbuf(p, &c); + // TODO renew all pointers + } + + 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); + c.error = err; + +error:; + response_err_ind(r, c.error, 0); + sk_send(p->sock, AGENTX_HEADER_SIZE); + return pkt - pkt_start; +} + +/* agentx-CommitSet-PDU */ +static uint +parse_commit_set_pdu(struct snmp_proto *p, byte *pkt, uint size) +{ + // don't forget to free resoures allocated by parse_test_set_pdu() + //mb_free(tr); + return parse_set_pdu(p, pkt, size, AGENTX_RES_COMMIT_FAILED); +} + +/* agentx-UndoSet-PDU */ +static uint +parse_undo_set_pdu(struct snmp_proto *p, byte *pkt, uint size) +{ + // don't forget to free resources allocated by parse_test_set_pdu() + //mb_free(tr); + return parse_set_pdu(p, pkt, size, AGENTX_RES_UNDO_FAILED); +} + +/* agentx-CleanupSet-PDU */ +static uint +parse_cleanup_set_pdu(struct snmp_proto *p, byte *pkt, uint size) +{ + // don't forget to free resources allocated by parse_test_set_pdu() + //mb_free(tr); + + if (size < AGENTX_HEADER_SIZE) + return 0; + + struct agentx_header *h = (void *) pkt; + return LOAD_U32(h->payload, h->flags & AGENTX_NETWORK_BYTE_ORDER); + + /* No agentx-Response-PDU is sent in response to agentx-CleanupSet-PDU */ +} + /** * parse_pkt - parse recieved response packet * @p: @@ -437,7 +678,6 @@ parse_pkt(struct snmp_proto *p, byte *pkt, uint size, uint *skip) if (size < AGENTX_HEADER_SIZE) return 0; - uint parsed_len = 0; struct agentx_header *h = (void *) pkt; //snmp_log("parse_pkt got type %s (%d)", snmp_pkt_type[h->type], h->type); @@ -447,33 +687,58 @@ parse_pkt(struct snmp_proto *p, byte *pkt, uint size, uint *skip) { case AGENTX_RESPONSE_PDU: //snmp_log("parse_pkt returning parse_response"); - parsed_len = parse_response(p, pkt, size); - break; + return parse_response(p, pkt, size); case AGENTX_GET_PDU: case AGENTX_GET_NEXT_PDU: case AGENTX_GET_BULK_PDU: refresh_ids(p, h); - parsed_len = parse_gets2_pdu(p, pkt, size, skip); - break; - - /* during testing the connection should stay opened (we die if we screw up - * and get CLOSE_PDU in response) + return parse_gets2_pdu(p, pkt, size, skip); case AGENTX_CLOSE_PDU: refresh_ids(p, h); - parsed_len = parse_close_pdu(p, pkt, size); - break; - */ + return parse_close_pdu(p, pkt, size); + + case AGENTX_TEST_SET_PDU: + refresh_ids(p, h); + return parse_test_set_pdu(p, pkt, size); + + case AGENTX_COMMIT_SET_PDU: + refresh_ids(p, h); + return parse_commit_set_pdu(p, pkt, size); + + case AGENTX_UNDO_SET_PDU: + refresh_ids(p, h); + return parse_undo_set_pdu(p, pkt, size); + + case AGENTX_CLEANUP_SET_PDU: + refresh_ids(p, h); + return parse_cleanup_set_pdu(p, pkt, size); default: /* drop the packet with unknown type silently */ //snmp_log("unknown packet type %u", h->type); return 0; } +} - //snmp_log("parse_pkt returning parsed length"); - return parsed_len; +static void +snmp_register_ok(struct snmp_proto *p, struct agentx_response *r, uint size, u8 type) +{ + (void)p;(void)r;(void)size;(void)type; +} + +static void +snmp_register_failed(struct snmp_proto *p, struct agentx_response *r, uint size, u8 type) +{ + (void)p;(void)r;(void)size;(void)type; +} + +static void +unsupported_context(struct snmp_proto *p, struct agentx_response *r, uint size) +{ + (void)p;(void)r;(void)size; + // TODO unsupported_context } static uint @@ -506,13 +771,58 @@ parse_response(struct snmp_proto *p, byte *res, uint size) */ //snmp_log(" pkt size %u", h->payload); - //snmp_log(" pkt size %u", h->payload); + switch (r->error) + { + case AGENTX_RES_NO_ERROR: + do_response(p, res, size); + break; - if (r->error == AGENTX_RES_NO_ERROR) - do_response(p, res, size); - else - /* erronous packet should be dropped quietly */ - {}//snmp_log("an error occured '%s'", snmp_errs[get_u16(&r->error) - SNMP_ERR_SHIFT]); + case AGENTX_RES_NOT_OPEN: + if (p->state == SNMP_LOCKED || p->state == SNMP_INIT) + snmp_startup(p); + else + snmp_connected(p->sock); + break; + + case AGENTX_RES_OPEN_FAILED: + if (p->state == SNMP_LOCKED || p->state == SNMP_INIT) + { + ASSUME(p->startup_timer); + p->startup_timer->hook = snmp_startup_timeout; + // TODO: better timeout + tm_set(p->startup_timer, current_time() + p->timeout S); + } + else + { + ASSUME(p->startup_timer); + p->startup_timer->hook = snmp_reconnect; + // TODO: better timeout + tm_set(p->startup_timer, current_time() + p->timeout S); + } + break; + + /* Registration errors */ + case AGENTX_RES_DUPLICATE_REGISTER: + case AGENTX_RES_REQUEST_DENIED: + snmp_register_failed(p, r, size, h->type); + break; + + case AGENTX_RES_UNSUPPORTED_CONTEXT: + unsupported_context(p, r, size); + break; + + /* We are trying to unregister a MIB, the unknownRegistration has same + * effect as success */ + case AGENTX_RES_UNKNOWN_REGISTER: + case AGENTX_RES_UNKNOWN_AGENT_CAPS: + case AGENTX_RES_PARSE_ERROR: + case AGENTX_RES_PROCESSING_ERR: + default: + /* erronous packet should be dropped quietly */ + // TODO correct error? + snmp_log("recieved response with error '%s'", snmp_errs[get_u16(&r->error) - SNMP_ERR_SHIFT]); + break; + } return pkt_size + AGENTX_HEADER_SIZE; } diff --git a/proto/snmp/subagent.h b/proto/snmp/subagent.h index 937b2de9..c57542b0 100644 --- a/proto/snmp/subagent.h +++ b/proto/snmp/subagent.h @@ -289,7 +289,9 @@ enum agentx_response_err { AGENTX_RES_NO_CREATION = 11, AGENTX_RES_INCONSISTENT_VALUE = 12, AGENTX_RES_RESOURCE_UNAVAILABLE = 13, - AGENTX_RES_NOT_WRITEABLE = 17, + AGENTX_RES_COMMIT_FAILED = 14, + AGENTX_RES_UNDO_FAILED = 15, + AGENTX_RES_NOT_WRITABLE = 17, AGENTX_RES_INCONSISTENT_NAME = 18, /* end of TEST_SET_PDU resonse errs (master -> subagent) */ AGENTX_RES_OPEN_FAILED = 256,