]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
tmp
authorVojtech Vilimek <vojtech.vilimek@nic.cz>
Sat, 17 Dec 2022 17:16:19 +0000 (18:16 +0100)
committerVojtech Vilimek <vojtech.vilimek@nic.cz>
Sat, 17 Dec 2022 17:16:19 +0000 (18:16 +0100)
proto/snmp/bgp_mib.c
proto/snmp/snmp.c
proto/snmp/snmp.h
proto/snmp/snmp_utils.c
proto/snmp/snmp_utils.h
proto/snmp/subagent.c
proto/snmp/subagent.h

index 07026a05933b295a24c90d014614dbbd0c240c27..4f2d5ef82a6eab25557bbe818659fcf47b3fc1b6 100644 (file)
@@ -15,7 +15,7 @@
 #include "subagent.h"
 #include "bgp_mib.h"
 
-static const char * const debug_bgp_states[] = {
+static const char * const debug_bgp_states[] UNUSED = {
   [BGP_INTERNAL_INVALID] = "BGP_INTERNAL_INVALID",
   [BGP_INTERNAL_BGP] = "BGP_INTERNAL_BGP",
   [BGP_INTERNAL_VERSION] = "BGP_INTERNAL_VERSION",
@@ -55,17 +55,17 @@ snmp_bgp_register(struct snmp_proto *p)
 {
   snmp_log("snmp_bgp_register()");
 
-  u32 arr_bgp[] = {1, 15, 1};
+  u32 bgp_mib_prefix[] = {1, 15, 1};
 
   { /* registering whole BGP4-MIB subtree */
-    snmp_log("snmp_proto %p (%p)", p, p->p.pool);
+    //snmp_log("snmp_proto %p (%p)", p, p->p.pool);
     struct snmp_register *registering = snmp_register_create(p, SNMP_BGP4_MIB);
 
     struct oid *oid = mb_alloc(p->p.pool, snmp_oid_sizeof(2));
     put_u8(&oid->n_subid, 2);
     put_u8(&oid->prefix, 2);
 
-    memcpy(oid->ids, arr_bgp, 2 * sizeof(u32));
+    memcpy(oid->ids, bgp_mib_prefix, 2 * sizeof(u32));
 
     registering->oid = oid;
     add_tail(&p->register_queue, &registering->n);
@@ -76,14 +76,14 @@ snmp_bgp_register(struct snmp_proto *p)
 
   // TODO squash bgpVersion and bgpLocalAs to one PDU
   { /* registering BGP4-MIB::bgpVersion */
-    snmp_log("snmp_proto %p (%p)", p, p->p.pool);
+    //snmp_log("snmp_proto %p (%p)", p, p->p.pool);
     struct snmp_register *registering = snmp_register_create(p, SNMP_BGP4_MIB);
 
     struct oid *oid = mb_alloc(p->p.pool, snmp_oid_sizeof(3));
     put_u8(&oid->n_subid, 3);
     put_u8(&oid->prefix, 2);
 
-    memcpy(oid->ids, arr_bgp, 3 * sizeof(u32));
+    memcpy(oid->ids, bgp_mib_prefix, 3 * sizeof(u32));
 
     registering->oid = oid;
     add_tail(&p->register_queue, &registering->n);
@@ -99,7 +99,7 @@ snmp_bgp_register(struct snmp_proto *p)
     put_u8(&oid->n_subid, 3);
     put_u8(&oid->prefix, 2);
 
-    memcpy(oid->ids, arr_bgp, 2 * sizeof(u32));
+    memcpy(oid->ids, bgp_mib_prefix, 2 * sizeof(u32));
     STORE(oid->ids[2], 2);
 
     registering->oid = oid;
@@ -116,7 +116,7 @@ snmp_bgp_register(struct snmp_proto *p)
     put_u8(&oid->n_subid, 3);
     put_u8(&oid->prefix, 2);
 
-    memcpy(oid->ids, arr_bgp, 2 * sizeof(u32));
+    memcpy(oid->ids, bgp_mib_prefix, 2 * sizeof(u32));
     STORE(oid->ids[2], 3);
 
     registering->oid = oid;
@@ -128,7 +128,7 @@ snmp_bgp_register(struct snmp_proto *p)
 
   /* register dynamic BGP4-MIB::bgpPeerEntry.* */
 
-  u32 arr_with_prefix[] = { 1, 15, 3, 1, 1};
+  u32 bgp_peer_entry[] = { 1, 15, 3, 1, 1};
   snmp_log("before hash walk - registering dynamic parts");
   HASH_WALK(p->bgp_hash, next, peer)
   {
@@ -139,7 +139,7 @@ snmp_bgp_register(struct snmp_proto *p)
     put_u8(&oid->n_subid, 9);
     put_u8(&oid->prefix, 2);
 
-    memcpy(oid->ids, arr_with_prefix, 5 * sizeof(u32));
+    memcpy(oid->ids, bgp_peer_entry, 5 * sizeof(u32));
 
     snmp_oid_ip4_index(oid, 5, ipa_to_ip4(peer->peer_ip));
 
@@ -262,6 +262,7 @@ print_bgp_record_all(struct snmp_proto *p)
     print_bgp_record(peer->config);
   }
   HASH_WALK_END;
+  snmp_log("dumping watched end");
 }
 
 /**
@@ -569,33 +570,53 @@ bgp_find_dynamic_oid(struct snmp_proto *p, struct oid *o_start, struct oid *o_en
   ip4_addr ip4 = ip4_from_oid(o_start);
   ip4_addr dest = ip4_from_oid(o_end);
 
-  snmp_log("ip addresses build");
+  snmp_log("ip addresses build (ip4) %I (dest) %I", ip4, dest);
+
+  // why am I allocated dynamically ?!
   net_addr *net = mb_allocz(p->p.pool, sizeof(struct net_addr));
   net_fill_ip4(net, ip4, IP4_MAX_PREFIX_LENGTH);
 
   snmp_log("dynamic part of BGP mib");
 
+  // why am I allocated dynamically ?!
   struct f_trie_walk_state *ws = mb_allocz(p->p.pool,
                                           sizeof(struct f_trie_walk_state));
 
   trie_walk_init(ws, p->bgp_trie, NULL);
 
-  if (trie_walk_next(ws, net) && ip4_less(net4_prefix(net), dest))
+  snmp_log("walk init");
+
+  if (trie_walk_next(ws, net)) // && ip4_less(net4_prefix(net), dest))
   {
-    struct oid *o = mb_allocz(p->p.pool, snmp_oid_sizeof(9));
-    o->n_subid = 9;
+    snmp_log("trie_walk_next() returned true");
+    if (ip4_less(net4_prefix(net), dest))  // <- delete me
+    {
+      snmp_log("ip4_less() returned treu");
+      struct oid *o = mb_allocz(p->p.pool, snmp_oid_sizeof(9));
+      o->n_subid = 9;
 
-    memcpy(o, o_start, snmp_oid_size(o_start));
-    snmp_oid_ip4_index(o, 5, net4_prefix(net));
+      memcpy(o, o_start, snmp_oid_size(o_start));
+      snmp_oid_ip4_index(o, 5, net4_prefix(net));
 
-    mb_free(net);
-    mb_free(ws);
+      mb_free(net);
+      mb_free(ws);
+
+      return o;
+    }
 
-    return o;
+    // delete me
+    else
+    {
+      snmp_log("ip4_less() returned false");
+      mb_free(net);
+      mb_free(ws);
+    }
+    // delete me end
   }
 
   else
   {
+    snmp_log("trie_walk_next() returned false, cleaning");
     mb_free(net);
     mb_free(ws);
   }
@@ -607,6 +628,8 @@ static struct oid *
 search_bgp_dynamic(struct snmp_proto *p, struct oid *o_start, struct oid *o_end, uint contid
 UNUSED, u8 next_state)
 {
+  snmp_log("search_bgp_dynamic() dynamic part Yaaay!");
+
   /* TODO can be remove after implementing all BGP4-MIB::bgpPeerTable columns */
   struct oid *copy = o_start;
   do {
@@ -630,13 +653,13 @@ search_bgp_mib(struct snmp_proto *p, struct oid *o_start, struct oid *o_end, uin
   //u8 state_end = (o_end) ? snmp_bgp_state(o_end) : 0;
 
 
-
   // print debugging information
   print_bgp_record_all(p);
 
   if (o_start->include && snmp_bgp_has_value(start_state) &&
       !is_dynamic(start_state) && o_start->n_subid == 3)
   {
+    snmp_log("search_bgp_mib() first search element (due to include field) returned");
     o_start->include = 0;  /* disable including for next time */
     return o_start;
   }
@@ -644,9 +667,13 @@ search_bgp_mib(struct snmp_proto *p, struct oid *o_start, struct oid *o_end, uin
   /* if state is_dynamic() then has more value and need find the right one */
   else if (!is_dynamic(start_state))
   {
+    snmp_log("seach_bgp_mib() static part");
     u8 next_state = snmp_bgp_next_state(start_state);
     o_start = update_bgp_oid(o_start, next_state);
 
+    snmp_log("search_bgp_mib() is NOT next_state dynamic %s",
+      !is_dynamic(next_state) ? "true" : "false");
+
     if (!is_dynamic(next_state))
       return o_start;
 
@@ -689,6 +716,7 @@ UNUSED, uint contid UNUSED, int byte_ord UNUSED, u8 state)
        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);
     }
 
     /* binded bgp protocol not found */
index e383f85d60387f8c361902286a0e63173713d809..8525d572c2ddf0c6c40febb2ae042eed0c19153d 100644 (file)
@@ -25,11 +25,14 @@ static void snmp_start_locked(struct object_lock *lock);
 
 
 static const char * const snmp_state[] = {
-  [SNMP_ERR]     = "SNMP ERROR",
-  [SNMP_DELAY]   = "SNMP DELAY",
-  [SNMP_INIT]    = "SNMP INIT",
-  [SNMP_REGISTR]  = "SNMP REGISTERING",
-  [SNMP_CONN]    = "SNMP CONNECTED",
+  [SNMP_ERR]         = "SNMP ERROR",
+  [SNMP_DELAY]       = "SNMP DELAY",
+  [SNMP_INIT]        = "SNMP INIT",
+  [SNMP_REGISTER]     = "SNMP REGISTERING",
+  [SNMP_CONN]        = "SNMP CONNECTED",
+  [SNMP_STOP]        = "SNMP STOP",
+  [SNMP_DOWN]        = "SNMP DOWN",
+  [SNMP_LISTEN]              = "SNMP LISTEN",
 };
 
 static struct proto *
@@ -57,14 +60,26 @@ snmp_init(struct proto_config *CF)
   return P;
 }
 
-static void snmp_down(struct snmp_proto *p)
+static inline void
+snmp_cleanup(struct snmp_proto *p)
 {
+  rfree(p->startup_timer);
+  rfree(p->ping_timer);
+
   if (p->sock != NULL)
-    mb_free(p->sock);
+    rfree(p->sock);
 
   if (p->lock != NULL)
     rfree(p->lock);
 
+  p->state = SNMP_DOWN;
+}
+
+void
+snmp_down(struct snmp_proto *p)
+{
+  snmp_cleanup(p);
+
   proto_notify_state(&p->p, PS_DOWN);
 }
 
@@ -75,13 +90,23 @@ snmp_startup_timeout(timer *t)
   snmp_startup(t->data);
 }
 
+static void
+snmp_stop_timeout(timer *t)
+{
+  snmp_log("stop timer triggered");
+
+  struct snmp_proto *p = t->data;
+
+  snmp_down(p);
+}
+
 static void
 snmp_startup(struct snmp_proto *p)
 {
   //snmp_log("changing proto_snmp state to INIT");
 
   if (p->state == SNMP_CONN ||
-      p->state == SNMP_REGISTR)
+      p->state == SNMP_REGISTER)
   {
     snmp_log("startup() with invalid state %u", p->state);
     return;
@@ -118,7 +143,7 @@ snmp_startup(struct snmp_proto *p)
 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;
 
   sock *s = sk_new(p->p.pool);
@@ -189,6 +214,7 @@ snmp_sock_err(sock *sk, int err)
 
   snmp_log("changing proto_snmp state to ERR[OR]");
   p->state = SNMP_ERR;
+
   // TODO ping interval
   tm_start(p->startup_timer, 15 S);
 }
@@ -381,13 +407,31 @@ snmp_shutdown(struct proto *P)
 {
   snmp_log("snmp_shutdown()");
   struct snmp_proto *p = SKIP_BACK(struct snmp_proto, p, P);
-  p->state = SNMP_INIT;
 
   tm_stop(p->ping_timer);
-  tm_stop(p->startup_timer);
 
-  snmp_stop_subagent(p);
-  return PS_DOWN;
+  /* connection established => close the connection */
+  if (p->state == SNMP_CONN)
+  {
+    p->state = SNMP_STOP;
+
+    /* startup time is reused for connection closing */
+    p->startup_timer->hook = snmp_stop_timeout;
+
+    // TODO timeout duration ??
+    tm_set(p->startup_timer, 15 S);
+
+    snmp_stop_subagent(p);
+
+    return PS_STOP;
+  }
+
+  /* no connection to close */
+  else
+  {
+    snmp_cleanup(p);
+    return PS_DOWN;
+  }
 }
 
 struct protocol proto_snmp = {
index 8f4eede894651eb18a897f8a57b16ef0db2eeb45..acf1db20bbad35ec418b27ed22c029b2808cf465 100644 (file)
 #define SNMP_RX_BUFFER_SIZE 2048
 #define SNMP_TX_BUFFER_SIZE 2048
 
-#define SNMP_ERR 0
-#define SNMP_DELAY 1
-#define SNMP_INIT 2
-#define SNMP_REGISTR 3
-#define SNMP_CONN 4
+enum snmp_proto_state {
+  SNMP_ERR = 0,
+  SNMP_DELAY,
+  SNMP_INIT,
+  SNMP_REGISTER,
+  SNMP_CONN,
+  SNMP_STOP,
+  SNMP_DOWN,
+  SNMP_LISTEN,
+};
 
 /* hash table macros */
 #define SNMP_HASH_KEY(n)  n->peer_ip
index 225efd4c54f5e4f2f138865579f30979f177f648..9b044f05ac0080144a52970435dbba972ba1e9c1 100644 (file)
@@ -11,7 +11,7 @@
 #include "snmp_utils.h"
 
 /**
- * snmp_is_oid_empty - check if oid is null-valued 
+ * snmp_is_oid_empty - check if oid is null-valued
  * @oid: object identifier to check
  *
  * Test if the oid header is full of zeroes. For @oid NULL returns 0.
@@ -347,6 +347,8 @@ 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)
 {
+  snmp_log("snmp_register_ack()");
+
   struct snmp_register *reg;
   WALK_LIST(reg, p->register_queue)
   {
@@ -361,11 +363,24 @@ snmp_register_ack(struct snmp_proto *p, struct agentx_header *h)
       ro->oid = reg->oid;
 
       rem_node(&reg->n);
+      mb_free(reg);
       p->register_to_ack--;
 
       add_tail(&p->bgp_registered, &ro->n);
 
+      snmp_log("  register note find %u", list_length(&p->bgp_registered));
       return;
     }
   }
+
+  snmp_log("unknown registration");
+}
+
+void
+snmp_dump_packet(byte *pkt, uint size)
+{
+  snmp_log("dump");
+  for (int i = 0; i < size; i += 4)
+    snmp_log("pkt [%d]  0x%02x%02x%02x%02x", i, pkt[i],pkt[i+1],pkt[i+2],pkt[i+3]);
+  snmp_log("end dump");
 }
index f624fbd0f4e7e2a877767c8b510a852230cdfb29..3c38827d3712665897be2eb02a2cb607b39f3b85 100644 (file)
@@ -39,4 +39,6 @@ struct oid *snmp_prefixize(struct snmp_proto *p, struct oid *o, int byte_ord);
 struct snmp_register *snmp_register_create(struct snmp_proto *p, u8 mib_class);
 
 void snmp_register_ack(struct snmp_proto *p, struct agentx_header *h);
+
+void snmp_dump_packet(byte *pkt, uint size);
 #endif
index 44040a61f6e95d5ddd71a0a1617ed4a3b6c3cb24..c37e9e48371b2261a9827fbe02a895b796d2859d 100644 (file)
@@ -28,31 +28,31 @@ static byte *snmp_mib_fill(struct snmp_proto *p, struct oid *oid, u8 mib_class,
 byte *buf, uint size, struct snmp_error *error, uint contid, int byte_ord);
 
 static int parse_response(struct snmp_proto *p, byte *buf, uint size);
-static int snmp_stop_ack(sock *sk, uint size);
-static void do_response(struct snmp_proto *p, byte *buf, uint size);
-static uint parse_get_pdu(struct snmp_proto *p, byte *buf, uint size);
+// static int snmp_stop_ack(sock *sk, uint size);
+static int do_response(struct snmp_proto *p, byte *buf, uint size);
+// static uint parse_get_pdu(struct snmp_proto *p, byte *buf, uint size);
 static uint parse_gets_pdu(struct snmp_proto *p, byte *buf, uint size);
 static byte *prepare_response(struct snmp_proto *p, byte *buf, uint size);
 static void response_err_ind(byte *buf, uint err, uint ind);
 static struct oid *search_mib(struct snmp_proto *p, struct oid *o_start, struct oid *o_end, struct oid *o_curr, u8 mib_class, uint contid);
-static inline byte *find_n_fill(struct snmp_proto *p, struct oid *o, byte *buf, uint size, uint contid, int byte_ord);
+// static inline byte *find_n_fill(struct snmp_proto *p, struct oid *o, byte *buf, uint size, uint contid, int byte_ord);
 
 
 static const char * const snmp_errs[] = {
   #define SNMP_ERR_SHIFT 256
-  [AGENTX_RES_OPEN_FAILED - SNMP_ERR_SHIFT] = "Open failed",
-  [AGENTX_RES_NOT_OPEN - SNMP_ERR_SHIFT] = "Not open",
-  [AGENTX_RES_INDEX_WRONG_TYPE - SNMP_ERR_SHIFT] = "Index wrong type",
+  [AGENTX_RES_OPEN_FAILED        - SNMP_ERR_SHIFT] = "Open failed",
+  [AGENTX_RES_NOT_OPEN           - SNMP_ERR_SHIFT] = "Not open",
+  [AGENTX_RES_INDEX_WRONG_TYPE   - SNMP_ERR_SHIFT] = "Index wrong type",
   [AGENTX_RES_INDEX_ALREADY_ALLOC - SNMP_ERR_SHIFT] = "Index already allocated",
-  [AGENTX_RES_INDEX_NONE_AVAIL - SNMP_ERR_SHIFT] = "Index none availlable",
-  [AGENTX_RES_NOT_ALLOCATED - SNMP_ERR_SHIFT] = "Not allocated",
+  [AGENTX_RES_INDEX_NONE_AVAIL   - SNMP_ERR_SHIFT] = "Index none availlable",
+  [AGENTX_RES_NOT_ALLOCATED      - SNMP_ERR_SHIFT] = "Not allocated",
   [AGENTX_RES_UNSUPPORTED_CONTEXT - SNMP_ERR_SHIFT] = "Unsupported contex",
-  [AGENTX_RES_DUPLICATE_REGISTR - SNMP_ERR_SHIFT] = "Duplicate registration",
-  [AGENTX_RES_UNKNOWN_REGISTR - SNMP_ERR_SHIFT] = "Unknown registration",
-  [AGENTX_RES_UNKNOWN_AGENT_CAPS - SNMP_ERR_SHIFT] = "Unknown agent caps",
-  [AGENTX_RES_PARSE_ERROR - SNMP_ERR_SHIFT] = "Parse error",
-  [AGENTX_RES_REQUEST_DENIED - SNMP_ERR_SHIFT] = "Request denied",
-  [AGENTX_RES_PROCESSING_ERR - SNMP_ERR_SHIFT] = "Processing error",
+  [AGENTX_RES_DUPLICATE_REGISTER  - SNMP_ERR_SHIFT] = "Duplicate registration",
+  [AGENTX_RES_UNKNOWN_REGISTER   - SNMP_ERR_SHIFT] = "Unknown registration",
+  [AGENTX_RES_UNKNOWN_AGENT_CAPS  - SNMP_ERR_SHIFT] = "Unknown agent caps",
+  [AGENTX_RES_PARSE_ERROR        - SNMP_ERR_SHIFT] = "Parse error",
+  [AGENTX_RES_REQUEST_DENIED     - SNMP_ERR_SHIFT] = "Request denied",
+  [AGENTX_RES_PROCESSING_ERR     - SNMP_ERR_SHIFT] = "Processing error",
 };
 
 static const char * const snmp_pkt_type[] = {
@@ -114,7 +114,7 @@ open_pdu(struct snmp_proto *p, struct oid *oid)
     else if (ret < 0)
       snmp_log("sk_send err %d", ret);
     else
-      snmp_log("sk_send ok !!! ");
+      snmp_log("sk_send ok !!!");
   }
 
   else
@@ -318,12 +318,20 @@ parse_pkt(struct snmp_proto *p, byte *buf, uint size)
       log("sk_send OK ! !!");
   }
 
-  return len;
+  /* whole buffer was parsed while generating response */
+  if (len == size)
+    return 1; /* meaning buffer is empty */
+  else
+    return 0; /* meaning buffer stil contain some data to be parsed, parsing is not finished */
 }
 
 static int
 parse_response(struct snmp_proto *p, byte *buf, uint size)
 {
+  snmp_log("parse_response() g%u h%u", size, sizeof(struct agentx_header));
+
+  snmp_dump_packet(buf, size);
+
   if (size < sizeof(struct agentx_response))
     return 0;
 
@@ -332,15 +340,16 @@ parse_response(struct snmp_proto *p, byte *buf, uint size)
 
   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\t", 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("uptime: %u s", r->uptime);
 
   if (r->err == AGENTX_RES_NO_ERROR)
-    do_response(p, buf, size);
+    return do_response(p, buf, size);
   else
+    // TODO handle corrupted packets properly (and return appropriate retval)
     snmp_log("an error occured '%s'", snmp_errs[get_u16(&r->err) -
 SNMP_ERR_SHIFT]);
 
@@ -350,6 +359,7 @@ SNMP_ERR_SHIFT]);
 static inline int
 snmp_registered_all(struct snmp_proto *p)
 {
+  snmp_log("snmp_registered_all() %u", list_length(&p->register_queue));
   return p->register_to_ack == 0;
 }
 
@@ -362,21 +372,21 @@ snmp_register_mibs(struct snmp_proto *p) {
   snmp_log("registering all done");
 }
 
-
-
-static void
+static int
 do_response(struct snmp_proto *p, byte *buf, uint size UNUSED)
 {
   snmp_log("do_response()");
   struct agentx_response *r = (void *) buf;
   struct agentx_header *h = &r->h;
 
+  int network_byte_ord = h->flags & AGENTX_NETWORK_BYTE_ORDER;
+
   /* TODO make it asynchronous for better speed */
   switch (p->state)
   {
     case SNMP_INIT:
       /* parse open_pdu response */
-      if (h->flags & AGENTX_NETWORK_BYTE_ORDER)
+      if (network_byte_ord)
       {
        p->session_id = get_u32(&h->session_id);
        p->transaction_id = get_u32(&h->transaction_id);
@@ -387,14 +397,19 @@ do_response(struct snmp_proto *p, byte *buf, uint size UNUSED)
        memcpy(&p->session_id, &h->session_id, 12);
       }
 
-      snmp_register_mibs(p);
+      /* the state needs to be changed before sending registering PDUs to
+       * use correct do_response action on them
+       */
       snmp_log("changing state to REGISTER");
-      p->state = SNMP_REGISTR;
+      p->state = SNMP_REGISTER;
+      snmp_register_mibs(p);
+      snmp_log("do_response state SNMP_INIT register list %u", list_length(&p->register_queue));
 
       break;
 
-    case SNMP_REGISTR:
-      snmp_register_ack(p, h);
+    case SNMP_REGISTER:
+      snmp_log("do_response state SNMP_REGISTER register list %u", list_length(&p->register_queue));
+      snmp_register_ack(p ,h);
 
       if (snmp_registered_all(p)) {
        snmp_log("changing proto_snmp state to CONNECTED");
@@ -406,11 +421,28 @@ do_response(struct snmp_proto *p, byte *buf, uint size UNUSED)
       // proto_notify_state(&p->p, PS_UP);
       break;
 
+    case SNMP_STOP:
+      /* do nothing here */
+      break;
+
     default:
       die("unkonwn SNMP state");
   }
+
+  uint pkt_size = LOAD(h->payload, network_byte_ord) + sizeof(struct agentx_header);
+  snmp_log("do_response size %u pkt_size %u", size, pkt_size);
+  if (size > pkt_size)
+  {
+    memmove(buf, buf + pkt_size, size - pkt_size);
+    snmp_dump_packet(buf, size - pkt_size);
+    return 0;
+  }
+  else
+    /* all parsed */
+    return 1;
 }
 
+#if 0
 static uint UNUSED
 parse_get_pdu(struct snmp_proto *p, byte *buf, uint size)
 {
@@ -506,6 +538,7 @@ parse_get_pdu(struct snmp_proto *p, byte *buf, uint size)
 
   return 1;
 }
+#endif
 
 static u8
 get_mib_class(struct oid *oid)
@@ -620,7 +653,7 @@ snmp_get_bulk(struct snmp_proto *p, struct oid *o_start, struct oid *o_end, byte
       pkt += snmp_varbind_size(vb);
       vb->type = AGENTX_END_OF_MIB_VIEW;
     }
-    
+
     return pkt;
     #endif
   }
@@ -722,7 +755,7 @@ parse_gets_pdu(struct snmp_proto *p, byte *req, uint size)
 
        break;
 
-      case AGENTX_GET_BULK_PDU: 
+      case AGENTX_GET_BULK_PDU:
        res_pkt = snmp_get_bulk(p, o_start, o_end, res_pkt, rsize, &bulk_state, 0, byte_ord);
        break;
 
@@ -750,7 +783,7 @@ parse_gets_pdu(struct snmp_proto *p, byte *req, uint size)
        }
        break;
       }
-      #endif 
+      #endif
     }
 
     mb_free(o_start);
@@ -803,14 +836,10 @@ void
 snmp_stop_subagent(struct snmp_proto *p)
 {
   snmp_log("snmp_stop_subagent() state %s", p->state);
-  sock *sk = p->sock;
+  // sock *sk = p->sock;
 
-  if (p->state == SNMP_CONN)
-  {
+  if (p->state == SNMP_STOP)
     close_pdu(p, AGENTX_CLOSE_SHUTDOWN);
-
-    sk->rx_hook = snmp_stop_ack;
-  }
 }
 
 static inline int
@@ -873,7 +902,7 @@ snmp_ping(struct snmp_proto *p)
     snmp_log("ping_pdu() insufficient size");
 }
 
-
+#if 0
 static int
 snmp_stop_ack(sock *sk, uint size)
 {
@@ -883,9 +912,10 @@ snmp_stop_ack(sock *sk, uint size)
   if (size < AGENTX_HEADER_SIZE)
     return 0;
 
+  // TODO FIXME parse_response could return 0 even if waiting packet was parsed
   if (parse_response(p, buf, size))
   {
-    p->p.disabled = 1;
+    // p->p.disabled = 1;
     proto_notify_state(&p->p, PS_DOWN);
 
     //sk->tx_hook = NULL;
@@ -895,6 +925,7 @@ snmp_stop_ack(sock *sk, uint size)
   /* all done */
   return 0;
 }
+#endif
 
 /*
 void
@@ -976,12 +1007,31 @@ has_inet_prefix(struct oid *o)
          o->ids[3] == 1);
 }
 
-/* tree is tree with "internet" prefix .1.3.6.1 
-   working only with o_start, o_end allocated in heap (not from buffer)*/
-static struct oid *
-search_mib(struct snmp_proto *p, struct oid *o_start, struct oid *o_end, struct oid *o_curr, u8 mib_class, uint contid UNUSED)
+/**
+ * upper_bound_check - check if oid is before SearchRange end
+ *
+ * @found: best oid found in MIB tree
+ * @bound: upper bound specified in SearchRange
+ *
+ * check if found oid meet the SearchRange upper bound condition in
+ * lexicographical order, returns boolean value
+ */
+static int
+upper_bound_check(struct oid *found, struct oid *bound)
 {
-  snmp_log("search_mib()");
+  if (snmp_is_oid_empty(bound))
+    return 1;
+
+  if (snmp_oid_compare(found, bound) < 0)
+    return 0;
+
+  return 0;
+}
+
+static inline struct oid *
+search_mib_unchecked(struct snmp_proto *p, struct oid *o_start, struct oid *o_end, struct oid *o_curr, u8 mib_class UNUSED, uint contid UNUSED)
+{
+  snmp_log("search_mib_unchecked()");
 
   if (!o_start)
     return NULL;
@@ -1004,7 +1054,7 @@ search_mib(struct snmp_proto *p, struct oid *o_start, struct oid *o_end, struct
        if (o_curr != NULL)
          return o_curr;
 
-       
+
        /* fall through */
 
        /*
@@ -1015,7 +1065,7 @@ search_mib(struct snmp_proto *p, struct oid *o_start, struct oid *o_end, struct
            return o_curr;
          // fall through
         */
-       
+
       default:
         return NULL;
     }
@@ -1024,6 +1074,23 @@ search_mib(struct snmp_proto *p, struct oid *o_start, struct oid *o_end, struct
   return NULL;
 }
 
+/* tree is tree with "internet" prefix .1.3.6.1
+   working only with o_start, o_end allocated in heap (not from buffer)*/
+static struct oid *
+search_mib(struct snmp_proto *p, struct oid *o_start, struct oid *o_end, struct oid *o_curr, u8 mib_class, uint contid UNUSED)
+{
+  struct oid *found = search_mib_unchecked(p, o_start, o_end, o_curr, mib_class, contid);
+
+  if (upper_bound_check(found, o_end))
+    return found;
+  else {
+    mb_free(found);
+    return NULL;
+  }
+}
+
+// XXX moved to bgp_mib.c
+#if 0
 static byte *
 find_bgp_one(struct bgp_proto *bp, struct oid *o, byte *pkt, uint size UNUSED, uint contid UNUSED)
 {
@@ -1199,7 +1266,9 @@ find_bgp_one(struct bgp_proto *bp, struct oid *o, byte *pkt, uint size UNUSED, u
 
   return pkt;
 }
+#endif
 
+#if 0
 /* contid - context identification number */
 static byte *
 snmp_bgp_record(struct snmp_proto *p, struct oid *o, byte *buf, uint size, uint contid)
@@ -1269,6 +1338,7 @@ snmp_bgp_record(struct snmp_proto *p, struct oid *o, byte *buf, uint size, uint
 
   return pkt;
 }
+#endif
 
 /*
 static byte *
@@ -1279,6 +1349,7 @@ find_ospf_record(struct snmp_proto *p, struct oid *o, byte *buf, uint size)
 }
 */
 
+#if 0
 static inline byte *
 find_prefixed(struct snmp_proto *p, struct oid *o, byte *buf, uint size, uint contid)
 {
@@ -1311,6 +1382,7 @@ find_prefixed(struct snmp_proto *p, struct oid *o, byte *buf, uint size, uint co
       //return snmp_no_such_object(buf, vb);
   }
 }
+#endif
 
 /** 
  * snmp_prefixize - return prefixed oid copy if possible
@@ -1367,6 +1439,7 @@ snmp_prefixize(struct snmp_proto *proto, struct oid *oid, int byte_ord)
   return new;
 }
 
+#if 0
 static inline byte *
 find_n_fill(struct snmp_proto *p, struct oid *o, byte *buf, uint size, uint contid, int byte_ord)
 {
@@ -1378,6 +1451,7 @@ find_n_fill(struct snmp_proto *p, struct oid *o, byte *buf, uint size, uint cont
 
   return NULL;
 }
+#endif
 
 /**
  * snmp_mib_fill - 
index 27c878f742296a0ffea4af2f6f403d7a6c4f2ba6..431ce7598fbe2053997c41319bf8a27ab33e7af6 100644 (file)
@@ -264,8 +264,8 @@ enum agentx_response_err {
   AGENTX_RES_INDEX_NONE_AVAIL      = 260,
   AGENTX_RES_NOT_ALLOCATED         = 261,
   AGENTX_RES_UNSUPPORTED_CONTEXT    = 262,
-  AGENTX_RES_DUPLICATE_REGISTR     = 263,
-  AGENTX_RES_UNKNOWN_REGIST      = 264,
+  AGENTX_RES_DUPLICATE_REGISTER            = 263,
+  AGENTX_RES_UNKNOWN_REGISTER      = 264,
   AGENTX_RES_UNKNOWN_AGENT_CAPS            = 265,
   AGENTX_RES_PARSE_ERROR           = 266,
   AGENTX_RES_REQUEST_DENIED        = 267,
@@ -273,6 +273,8 @@ enum agentx_response_err {
 } PACKED;
 
 int snmp_rx(sock *sk, uint size);
+int snmp_rx_stop(sock *sk, uint size);
+void snmp_down(struct snmp_proto *p);
 void snmp_register(struct snmp_proto *p, struct oid *oid, uint index, uint len);
 void snmp_unregister(struct snmp_proto *p, struct oid *oid, uint index, uint len);