]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
SNMP: Fix snmp_test.c
authorVojtech Vilimek <vojtech.vilimek@nic.cz>
Thu, 15 Aug 2024 16:23:41 +0000 (18:23 +0200)
committerVojtech Vilimek <vojtech.vilimek@nic.cz>
Thu, 15 Aug 2024 16:23:41 +0000 (18:23 +0200)
proto/snmp/snmp_test.c
proto/snmp/snmp_utils.c
proto/snmp/snmp_utils.h
proto/snmp/subagent.c
proto/snmp/subagent.h

index e572d8860c271f868a13d040070dd2ed168f922a..f043cdfb983ab74b7b091d74c3718b27ab87564f 100644 (file)
 #include "snmp_utils.h"
 #include "mib_tree.h"
 
-/*************************************************************************
- *
- * TODO: reject OIDs longer than OID_MAX_LEN in subagent.c/snmp_utils.c
- *
- *************************************************************************/
-
-// TODO: limit for prefixed OID used for walking is 27 ids (32 - 4inet -1prefix
-// resp. 33 - 4inet-1prefix-1empty)
-
-// TODO test walk state stack overflow
-// TODO hint for child len alloc size
-
 static int t_oid_empty(void);
 static int t_oid_compare(void);
-static int t_oid_prefixize(void);
+static int t_varbind_name_to_tx(void);
 static int t_walk_oid_desc(void);
 static int t_walk_oid_compare(void);
 static int t_tree_find(void);
@@ -398,49 +386,76 @@ t_oid_compare(void)
   return 1;
 }
 
-static struct oid *
-snmp_oid_prefixize(struct snmp_proto *p, const struct oid *oid, struct snmp_pdu *c)
+static inline void
+fix_byteorder(u32 *ids, u32 len)
 {
-  snmp_vb_to_tx(c, oid);
-  struct agentx_varbind *vb = c->sr_vb_start;
-  bt_assert(vb->reserved == 0);
-  return &vb->name;
+  for (u32 i = 0; i < len; i++)
+    STORE_U32(ids[i], ids[i]);
 }
 
-/*
- * t_oid_prefixize - test prefixing aspect of function snmp_vb_to_tx()
- */
+int
+u32cmp_bo(const u32 *cpu_native, const u32 *net_bo, u32 len)
+{
+  for (u32 i = 0; i < len; i++)
+  {
+    if (cpu_native[i] != LOAD_U32(net_bo[i]))
+      return LOAD_U32(net_bo[i]) - cpu_native[i];
+  }
+
+  return 0;
+}
+
+#define CREATE_RANDOM(gen)     \
+  ({  \
+    struct oid *_o = gen(); \
+    fix_byteorder(_o->ids, _o->n_subid);  \
+    _o; \
+  })
+
 static int
-t_oid_prefixize(void)
+t_varbind_name_to_tx(void)
 {
-  lp_state tmps = { };
-  struct snmp_proto *snmp_proto = NULL;
+  /* Test snmp_vb_name_to_tx() */
 
-  byte *buffer = tmp_alloc(SNMP_BUFFER_SIZE);
-  const struct snmp_pdu copy = {
+  lp_state tmps = { };
+  struct snmp_proto *snmp_proto = tmp_alloc(sizeof(struct snmp_proto));
+  memset(snmp_proto, 0, sizeof(struct snmp_proto));
+  sock *s = sk_new(&root_pool);
+  snmp_proto->sock = s;
+  /* dirty hack sk_alloc_bufs() */
+  s->tbsize = SNMP_BUFFER_SIZE;
+  s->tbuf = s->tbuf_alloc = xmalloc(s->tbsize);
+  void *buffer = s->tbuf;
+
+  struct snmp_pdu copy = {
+    .p = snmp_proto,
+    .sr_vb_start = (void *) buffer,
     .buffer = buffer,
-    .size = SNMP_BUFFER_SIZE,
-    .error = AGENTX_RES_NO_ERROR,
-    .index = 0,
   };
-  struct snmp_pdu c;
+  struct snmp_pdu c = copy;
+  struct oid *new;
+  struct agentx_varbind *vb;
 
   lp_save(tmp_linpool, &tmps);
 
-
   /* testing prefixable OIDs */
   for (int test = 0; test < TESTS_NUM; test++)
   {
-    const struct oid *oid = random_prefixable_oid();
+    const struct oid *oid = CREATE_RANDOM(random_prefixable_oid);
+
+    /* both LOAD_U8() and STORE_U8() are pointless as it byteorder does not
+     * influence single byte values.
+     */
 
     u8 subids = oid->n_subid;
     u8 include = oid->include;
-    u32 pid = oid->ids[ARRAY_SIZE(snmp_internet)];
+    u32 pid = LOAD_U32(oid->ids[ARRAY_SIZE(snmp_internet)]);
 
     /* reset to the default snmp_pdu */
     c = copy; memset(buffer, 0, snmp_oid_size(oid) + 8);
 
-    struct oid *new = snmp_oid_prefixize(snmp_proto, oid, &c);
+    vb = snmp_vb_name_to_tx(&c, oid);
+    new = &vb->name;
 
     bt_assert(new->n_subid == subids - (ARRAY_SIZE(snmp_internet) + 1));
     bt_assert(new->prefix == pid);
@@ -449,11 +464,11 @@ t_oid_prefixize(void)
 
     for (u32 i = 0; i < new->n_subid; i++)
     {
-      bt_assert(new->ids[i] == oid->ids[i + ARRAY_SIZE(snmp_internet) + 1]);
+      bt_assert(new->ids[i] == LOAD_U32(oid->ids[i + ARRAY_SIZE(snmp_internet) + 1]));
     }
 
     for (u32 j = 0; j < ARRAY_SIZE(snmp_internet); j++)
-      bt_assert(oid->ids[j] == snmp_internet[j]);
+      bt_assert(LOAD_U32(oid->ids[j]) == snmp_internet[j]);
 
     lp_restore(tmp_linpool, &tmps);
   }
@@ -461,18 +476,19 @@ t_oid_prefixize(void)
   /* testing already prefixed OIDs */
   for (int test = 0; test < TESTS_NUM; test++)
   {
-    const struct oid *prefixed = random_prefixed_oid();
+    const struct oid *prefixed = CREATE_RANDOM(random_prefixed_oid);
 
     /* reset to the default snmp_pdu */
     c = copy; memset(buffer, 0, snmp_oid_size(prefixed) + 8);
 
-    struct oid *new = snmp_oid_prefixize(snmp_proto, prefixed, &c);
+    vb = snmp_vb_name_to_tx(&c, prefixed);
+    new = &vb->name;
 
     bt_assert(new->n_subid == prefixed->n_subid);
     bt_assert(new->prefix == prefixed->prefix);
     bt_assert(!!new->include == !!prefixed->include);
     bt_assert(new->reserved == 0);
-    bt_assert(!memcmp(&new->ids[0], &prefixed->ids[0], new->n_subid * sizeof(u32)));
+    bt_assert(!u32cmp_bo(&new->ids[0], &prefixed->ids[0], new->n_subid));
 
     lp_restore(tmp_linpool, &tmps);
   }
@@ -482,14 +498,14 @@ t_oid_prefixize(void)
   /* testing non-prefixable OIDs */
   for (int test = 0; test < TESTS_NUM; test++)
   {
-    const struct oid *oid = random_no_prefix_oid();
+    const struct oid *oid = CREATE_RANDOM(random_no_prefix_oid);
 
     /* test that the OID is _really_ not prefixable */
     if (oid->n_subid > ARRAY_SIZE(snmp_internet) &&
-       oid->ids[ARRAY_SIZE(snmp_internet) + 1] <= UINT8_MAX)
+       LOAD_U32(oid->ids[ARRAY_SIZE(snmp_internet) + 1]) <= UINT8_MAX)
     {
       for (u32 i = 0; i < ARRAY_SIZE(snmp_internet); i++)
-       if (oid->ids[i] != snmp_internet[i]) goto continue_testing;
+       if (LOAD_U32(oid->ids[i]) != snmp_internet[i]) goto continue_testing;
 
       break; /* outer for loop */
     }
@@ -499,13 +515,14 @@ continue_testing:
     /* reset to the default snmp_pdu */
     c = copy; memset(buffer, 0, snmp_oid_size(oid) + 8);
 
-    struct oid *new = snmp_oid_prefixize(snmp_proto, oid, &c);
+    vb = snmp_vb_name_to_tx(&c, oid);
+    new = &vb->name;
 
     bt_assert(new->n_subid == oid->n_subid);
     bt_assert(new->prefix == oid->prefix);
     bt_assert(!!new->include == !!oid->include);
     bt_assert(new->reserved == 0);
-    bt_assert(!memcmp(&new->ids[0], &oid->ids[0], new->n_subid * sizeof(u32)));
+    bt_assert(!u32cmp_bo(&new->ids[0], &oid->ids[0], new->n_subid));
 
     lp_restore(tmp_linpool, &tmps);
   }
@@ -515,15 +532,16 @@ continue_testing:
     const struct oid *oid;
     {
       struct oid *work = random_prefixable_oid();
+      fix_byteorder(work->ids, work->n_subid);
 
       /* include also the prefix ID (at index 4) */
       u32 index = xrandom(ARRAY_SIZE(snmp_internet) + 1);
       /* change randomly picked id at index from 0..5 (included) */
       u32 random = bt_random();
       if (index == ARRAY_SIZE(snmp_internet) && random > 255)
-       work->ids[index] = random;
+       work->ids[index] = VALUE_U32(random);
       else if (index != ARRAY_SIZE(snmp_internet) && work->ids[index] != random)
-       work->ids[index] = random;
+       work->ids[index] = VALUE_U32(random);
       else
        continue;
       oid = work;
@@ -532,17 +550,19 @@ continue_testing:
     /* reset to the default snmp_pdu */
     c = copy; memset(buffer, 0, snmp_oid_size(oid) + 8);
 
-    struct oid *new = snmp_oid_prefixize(snmp_proto, oid, &c);
+    vb = snmp_vb_name_to_tx(&c, oid);
+    new = &vb->name;
 
     bt_assert(new->n_subid == oid->n_subid);
     bt_assert(new->prefix == oid->prefix);
     bt_assert(!!new->include == !!oid->include);
     bt_assert(new->reserved == 0);
-    bt_assert(!memcmp(&new->ids[0], &oid->ids[0], new->n_subid * sizeof(u32)));
+    bt_assert(!u32cmp_bo(&new->ids[0], &oid->ids[0], new->n_subid));
 
     lp_restore(tmp_linpool, &tmps);
   }
 
+  rfree(snmp_proto->sock);
   tmp_flush();
   return 1;
 }
@@ -1934,7 +1954,7 @@ int main(int argc, char **argv)
 
   bt_test_suite(t_oid_empty, "Function that determines if the OID is empty");
   bt_test_suite(t_oid_compare, "Function defining lexicographical order on OIDs");
-  bt_test_suite(t_oid_prefixize, "Function transforming OID to prefixed form");
+  bt_test_suite(t_varbind_name_to_tx, "Function loading OID from RX buffer with prefixation");
   bt_test_suite(t_oid_ancestor, "Function finding common ancestor of two OIDs");
   bt_test_suite(t_walk_to_oid, "Function transforming MIB tree walk state to OID");
   bt_test_suite(t_walk_oid_desc, "Function testing relation being subtree between MIB tree walk and OID");
index 42de8f9904e8a6647ecd72ca566846846b080243..a417b4b47652d3ec424d992f40aa0e2e8ec98552 100644 (file)
@@ -62,22 +62,22 @@ snmp_is_oid_empty(const struct oid *oid)
 
 /*
  * snmp_oid_is_prefixable - check for prefixed form conversion possibility
- * @oid: object identfier to check
+ * @oid: Object Identifier in packet byte order to check
  *
  * Check if it is possible to convert @oid to prefixed form. The condition of
  * that is standart .1.3.6.1 internet prefix and 5-th id that fits in one byte.
  */
 inline int
-snmp_oid_is_prefixable(const struct oid *oid)
+snmp_pkt_oid_is_prefixable(const struct oid *oid)
 {
-  if (oid->n_subid < 5)
+  if (LOAD_U8(oid->n_subid) < 5)
     return 0;
 
   for (int i = 0; i < 4; i++)
-    if (oid->ids[i] != snmp_internet[i])
+    if (LOAD_U32(oid->ids[i]) != snmp_internet[i])
       return 0;
 
-  if (oid->ids[4] >= 256)
+  if (LOAD_U32(oid->ids[4]) >= 256)
     return 0;
 
   return 1;
index b4010be52b5fb21c6205410b2afe419c28d91a82..870b338cc951c2760e454ad0472415ac09dbf3af 100644 (file)
@@ -21,7 +21,7 @@ size_t snmp_str_size(const char *str);
 
 /* type OID - Object Identifier */
 int snmp_is_oid_empty(const struct oid *oid);
-int snmp_oid_is_prefixable(const struct oid *oid);
+int snmp_pkt_oid_is_prefixable(const struct oid *oid);
 uint snmp_oid_size(const struct oid *o);
 size_t snmp_oid_size_from_len(uint n_subid);
 void snmp_oid_copy(struct oid *dest, const struct oid *src);
@@ -37,9 +37,16 @@ snmp_check_search_limit(const struct oid *search, const struct oid *limit)
   return snmp_is_oid_empty(limit) || snmp_oid_compare(search, limit) < 0;
 }
 
+/*
+ * snmp_oid_is_prefixed - test if OID is prefixed
+ * @oid: OID to use
+ *
+ * Works for both cpu native and packet byte order.
+ */
 static inline int
 snmp_oid_is_prefixed(const struct oid *oid)
 {
+  /* LOAD_U8() is in both cases basic mem load */
   return LOAD_U8(oid->prefix) != 0;
 }
 
index d94b2a799ef77f03a68aa5b158023ad4747067b2..b61f819b041a892e229b0da5abb081f708bbd4c1 100644 (file)
@@ -233,7 +233,7 @@ snmp_oid_prefixize_unsafe(struct oid *dest, const struct oid *src)
 }
 
 /*
- * snmp_vb_to_tx - create VarBind in TX buffer from RX buffer OID
+ * snmp_vb_name_to_tx - create VarBind in TX buffer from RX buffer OID
  * @c: PDU context
  * @oid: Object Identifier located in RX buffer with packet byte order
  *
@@ -242,7 +242,7 @@ snmp_oid_prefixize_unsafe(struct oid *dest, const struct oid *src)
  * of the name is optionally swapped to match cpu native byte order.
  */
 struct agentx_varbind *
-snmp_vb_to_tx(struct snmp_pdu *c, const struct oid *oid)
+snmp_vb_name_to_tx(struct snmp_pdu *c, const struct oid *oid)
 {
   uint vb_hdr_size = snmp_varbind_header_size(oid);
   (void) snmp_tbuf_reserve(c, vb_hdr_size);
@@ -253,7 +253,7 @@ snmp_vb_to_tx(struct snmp_pdu *c, const struct oid *oid)
   /* Move the c->buffer so that is points at &vb->name */
   vb->type = AGENTX_NULL;
 
-  if (snmp_oid_is_prefixable(oid) && !snmp_oid_is_prefixed(oid))
+  if (snmp_pkt_oid_is_prefixable(oid) && !snmp_oid_is_prefixed(oid))
   {
     u8 subids = LOAD_U8(oid->n_subid) - 5;
     ADVANCE(c->buffer, c->size, snmp_oid_size_from_len(subids));
@@ -301,7 +301,7 @@ snmp_load_oids(byte **pkt_ptr, uint *pkt_sz, struct snmp_pdu *c)
   }
 
   /* in cpu native byte order */
-  struct agentx_varbind *start_vb = snmp_vb_to_tx(c, start_buf);
+  struct agentx_varbind *start_vb = snmp_vb_name_to_tx(c, start_buf);
 
   /* in cpu native byte order */
   struct oid *end_oid = tmp_alloc(sz);
index 18bd1df11719a935eb9423566944ce02f0bc7422..7aab462357f17a750a63bd0382a1cd0b66293f3d 100644 (file)
@@ -344,7 +344,7 @@ 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);
 void snmp_notify_pdu(struct snmp_proto *p, struct oid *oid, void *data, uint size, int include_uptime);
 void snmp_register_mibs(struct snmp_proto *p);
-struct agentx_varbind *snmp_vb_to_tx(struct snmp_pdu *c, const struct oid *oid);
+struct agentx_varbind *snmp_vb_name_to_tx(struct snmp_pdu *c, const struct oid *oid);
 int snmp_tbuf_reserve(struct snmp_pdu *c, size_t bytes);
 
 static inline int