|
|
9a6c41 |
1172013 - NetworkManager causes snmp OID not increasing
|
|
|
9a6c41 |
|
|
|
9a6c41 |
commit 664ed943f63dfe9393e959840ecd23c31c9d8f89
|
|
|
9a6c41 |
Author: Bill Fenner <fenner@gmail.com>
|
|
|
9a6c41 |
Date: Wed Aug 27 16:02:57 2014 -0400
|
|
|
9a6c41 |
|
|
|
9a6c41 |
Handle duplicates in a binary_array container
|
|
|
9a6c41 |
|
|
|
9a6c41 |
The CONTAINER_KEY_ALLOW_DUPLICATES setting is fundamentally flawed;
|
|
|
9a6c41 |
it really effectively meant "I promise I won't insert duplicates
|
|
|
9a6c41 |
so don't check at insert time". However, the ip-forward-mib
|
|
|
9a6c41 |
sets this flag but relies on the duplicate prevention at insert
|
|
|
9a6c41 |
time under certain scenarios (e.g., multiple attachments to the
|
|
|
9a6c41 |
same subnet on MacOS), resulting in a loop in ip-forward-mib
|
|
|
9a6c41 |
in these scenarios. So, now it means "check for duplicates at
|
|
|
9a6c41 |
getnext time" - the binary search will find an arbitrary one
|
|
|
9a6c41 |
of the entries with the same key, and when we've incremented
|
|
|
9a6c41 |
we have to check whether or not we've actually incremented past
|
|
|
9a6c41 |
any duplicates. This costs an extra key compare per getnext.
|
|
|
9a6c41 |
|
|
|
9a6c41 |
If there's a scenario in the future where a MIB implementation
|
|
|
9a6c41 |
can really guarantee that it isn't inserting duplicates, we
|
|
|
9a6c41 |
might want to add a "CONTAINER_KEY_I_PROMISE_I_WONT_INSERT_DUPLICATES",
|
|
|
9a6c41 |
that disables the insertion check but doesn't perform the getnext
|
|
|
9a6c41 |
check.
|
|
|
9a6c41 |
|
|
|
9a6c41 |
diff --git a/snmplib/container_binary_array.c b/snmplib/container_binary_array.c
|
|
|
9a6c41 |
index 249a3a9..10ae67f 100644
|
|
|
9a6c41 |
--- a/snmplib/container_binary_array.c
|
|
|
9a6c41 |
+++ b/snmplib/container_binary_array.c
|
|
|
9a6c41 |
@@ -284,6 +284,22 @@ netsnmp_binary_array_get(netsnmp_container *c, const void *key, int exact)
|
|
|
9a6c41 |
if (key) {
|
|
|
9a6c41 |
if ((index = binary_search(key, c, exact)) == -1)
|
|
|
9a6c41 |
return NULL;
|
|
|
9a6c41 |
+ if (!exact &&
|
|
|
9a6c41 |
+ c->flags & CONTAINER_KEY_ALLOW_DUPLICATES) {
|
|
|
9a6c41 |
+ int result;
|
|
|
9a6c41 |
+
|
|
|
9a6c41 |
+ /*
|
|
|
9a6c41 |
+ * If duplicates are allowed, we have to be extra
|
|
|
9a6c41 |
+ * sure that we didn't just increment to a duplicate,
|
|
|
9a6c41 |
+ * thus causing a getnext loop.
|
|
|
9a6c41 |
+ */
|
|
|
9a6c41 |
+ result = c->compare(t->data[index], key);
|
|
|
9a6c41 |
+ while (result == 0) {
|
|
|
9a6c41 |
+ if (++index == t->count)
|
|
|
9a6c41 |
+ return NULL;
|
|
|
9a6c41 |
+ result = c->compare(t->data[index], key);
|
|
|
9a6c41 |
+ }
|
|
|
9a6c41 |
+ }
|
|
|
9a6c41 |
}
|
|
|
9a6c41 |
|
|
|
9a6c41 |
return t->data[index];
|
|
|
9a6c41 |
diff --git a/testing/fulltests/unit-tests/T021binary_array_oid_duplicates_clib.c b/testing/fulltests/unit-tests/T021binary_array_oid_duplicates_clib.c
|
|
|
9a6c41 |
new file mode 100644
|
|
|
9a6c41 |
index 0000000..c027329
|
|
|
9a6c41 |
--- /dev/null
|
|
|
9a6c41 |
+++ b/testing/fulltests/unit-tests/T021binary_array_oid_duplicates_clib.c
|
|
|
9a6c41 |
@@ -0,0 +1,72 @@
|
|
|
9a6c41 |
+/* HEADER Testing duplicate handling in binary OID array */
|
|
|
9a6c41 |
+
|
|
|
9a6c41 |
+/* Much copied from T012 */
|
|
|
9a6c41 |
+static const char test_name[] = "binary-array-of-OIDs-duplicate-test";
|
|
|
9a6c41 |
+oid o1 = 1;
|
|
|
9a6c41 |
+oid o2 = 2;
|
|
|
9a6c41 |
+oid o3 = 6;
|
|
|
9a6c41 |
+oid o4 = 8;
|
|
|
9a6c41 |
+oid o5 = 9;
|
|
|
9a6c41 |
+oid ox = 7;
|
|
|
9a6c41 |
+oid oy = 10;
|
|
|
9a6c41 |
+netsnmp_index i1, i2, i3, i4, i5, ix, iy, *ip;
|
|
|
9a6c41 |
+netsnmp_index *b[] = { &i4, &i2, &i3, &i1, &i5 };
|
|
|
9a6c41 |
+netsnmp_container *c;
|
|
|
9a6c41 |
+int i;
|
|
|
9a6c41 |
+
|
|
|
9a6c41 |
+init_snmp(test_name);
|
|
|
9a6c41 |
+
|
|
|
9a6c41 |
+c = netsnmp_container_get_binary_array();
|
|
|
9a6c41 |
+c->compare = netsnmp_compare_netsnmp_index;
|
|
|
9a6c41 |
+netsnmp_binary_array_options_set(c, 1,
|
|
|
9a6c41 |
+ CONTAINER_KEY_ALLOW_DUPLICATES);
|
|
|
9a6c41 |
+
|
|
|
9a6c41 |
+i1.oids = &o1;
|
|
|
9a6c41 |
+i2.oids = &o2;
|
|
|
9a6c41 |
+i3.oids = &o3;
|
|
|
9a6c41 |
+i4.oids = &o4;
|
|
|
9a6c41 |
+i5.oids = &o5;
|
|
|
9a6c41 |
+ix.oids = &ox;
|
|
|
9a6c41 |
+iy.oids = &oy;
|
|
|
9a6c41 |
+i1.len = i2.len = i3.len = i4.len = i5.len = ix.len = iy.len = 1;
|
|
|
9a6c41 |
+
|
|
|
9a6c41 |
+for (i = 0; i < sizeof(b)/sizeof(b[0]); ++i)
|
|
|
9a6c41 |
+ CONTAINER_INSERT(c, b[i]);
|
|
|
9a6c41 |
+
|
|
|
9a6c41 |
+#define MAX_ROUNDS 6
|
|
|
9a6c41 |
+/* Insert some duplicates of i4; also insert a duplicate of
|
|
|
9a6c41 |
+ * i1 to move the contents of the array around. */
|
|
|
9a6c41 |
+for (i = 0; i < MAX_ROUNDS; ++i) {
|
|
|
9a6c41 |
+ switch (i) {
|
|
|
9a6c41 |
+ case 0:
|
|
|
9a6c41 |
+ /* First round: no insert */
|
|
|
9a6c41 |
+ break;
|
|
|
9a6c41 |
+ case 1:
|
|
|
9a6c41 |
+ case 2:
|
|
|
9a6c41 |
+ case 4:
|
|
|
9a6c41 |
+ case 5:
|
|
|
9a6c41 |
+ /* Insert another duplicate of our target object */
|
|
|
9a6c41 |
+ CONTAINER_INSERT(c, &i4;;
|
|
|
9a6c41 |
+ break;
|
|
|
9a6c41 |
+ case 3:
|
|
|
9a6c41 |
+ /* Insert a dulicate of an earlier OID, so that it
|
|
|
9a6c41 |
+ * changes the binary search behavior */
|
|
|
9a6c41 |
+ CONTAINER_INSERT(c, &i1;;
|
|
|
9a6c41 |
+ break;
|
|
|
9a6c41 |
+ }
|
|
|
9a6c41 |
+ /* Primary requirement: getnext returns the next value! */
|
|
|
9a6c41 |
+ ip = CONTAINER_FIND(c, &i4;;
|
|
|
9a6c41 |
+ OKF(ip, ("FIND returned a value"));
|
|
|
9a6c41 |
+ OKF(c->compare(&i4, ip) == 0,
|
|
|
9a6c41 |
+ ("FIND returned oid %" NETSNMP_PRIo "d", ip->oids[0]));
|
|
|
9a6c41 |
+ ip = CONTAINER_NEXT(c, &i4;;
|
|
|
9a6c41 |
+ OKF(ip, ("NEXT returned a value"));
|
|
|
9a6c41 |
+ OKF(c->compare(&i5, ip) == 0,
|
|
|
9a6c41 |
+ ("NEXT returned index 5 = %" NETSNMP_PRIo "d", i5.oids[0]));
|
|
|
9a6c41 |
+}
|
|
|
9a6c41 |
+
|
|
|
9a6c41 |
+while ((ip = CONTAINER_FIRST(c)))
|
|
|
9a6c41 |
+ CONTAINER_REMOVE(c, ip);
|
|
|
9a6c41 |
+CONTAINER_FREE(c);
|
|
|
9a6c41 |
+
|
|
|
9a6c41 |
+snmp_shutdown(test_name);
|