Right now when we register a region with below that an instance we
can revert back in the tree. When we request below the instance we
currently use appl_region_next() to find the next region and simply
set the to be find oid to the the oid of the new region. In the
situation described above this means that we return the parent
region and set the oid to that of the parent region, which is smaller
than the instance oid.

The easiest fix is to increment the searched oid to nextsibling of the
instance and let the normal appl_varbind_backend() logic handle it from
there.

OK?

martijn@

Index: usr.sbin/snmpd/application.c
===================================================================
RCS file: /cvs/src/usr.sbin/snmpd/application.c,v
retrieving revision 1.25
diff -u -p -r1.25 application.c
--- usr.sbin/snmpd/application.c        27 Oct 2023 10:32:11 -0000      1.25
+++ usr.sbin/snmpd/application.c        28 Oct 2023 07:57:23 -0000
@@ -1368,19 +1368,17 @@ appl_varbind_backend(struct appl_varbind
                                        return -1;
                                return 0;
                        }
-                       if ((region = appl_region_next(ureq->aru_ctx,
-                           &(vb->av_oid), region)) == NULL)
-                               goto eomv;
                        vb->av_oid = region->ar_oid;
+                       ober_oid_nextsibling(&(vb->av_oid));
                        vb->av_include = 1;
+                       return appl_varbind_backend(ivb);
                }
        } else if (cmp == 0) {
                if (region->ar_instance && next && !vb->av_include) {
-                       if ((region = appl_region_next(ureq->aru_ctx,
-                           &(vb->av_oid), region)) == NULL)
-                               goto eomv;
                        vb->av_oid = region->ar_oid;
+                       ober_oid_nextsibling(&(vb->av_oid));
                        vb->av_include = 1;
+                       return appl_varbind_backend(ivb);
                }
        }
        ivb->avi_region = region;
Index: regress/usr.sbin/snmpd/Makefile
===================================================================
RCS file: /cvs/src/regress/usr.sbin/snmpd/Makefile,v
retrieving revision 1.6
diff -u -p -r1.6 Makefile
--- regress/usr.sbin/snmpd/Makefile     27 Oct 2023 10:26:20 -0000      1.6
+++ regress/usr.sbin/snmpd/Makefile     28 Oct 2023 07:57:23 -0000
@@ -170,6 +170,9 @@ BACKEND_TARGETS+=           backend_getnext_stale
 BACKEND_TARGETS+=              backend_getnext_inclusive_backwards
 BACKEND_TARGETS+=              backend_getnext_toofew
 BACKEND_TARGETS+=              backend_getnext_toomany
+BACKEND_TARGETS+=              
backend_getnext_instance_below_region_before_instance
+BACKEND_TARGETS+=              
backend_getnext_instance_below_region_on_instance
+BACKEND_TARGETS+=              
backend_getnext_instance_below_region_below_instance
 BACKEND_TARGETS+=              backend_getbulk_nonrep_zero_maxrep_one
 BACKEND_TARGETS+=              backend_getbulk_nonrep_zero_maxrep_two
 BACKEND_TARGETS+=              backend_getbulk_nonrep_one_maxrep_one
Index: regress/usr.sbin/snmpd/backend.c
===================================================================
RCS file: /cvs/src/regress/usr.sbin/snmpd/backend.c,v
retrieving revision 1.1
diff -u -p -r1.1 backend.c
--- regress/usr.sbin/snmpd/backend.c    24 Oct 2023 14:34:40 -0000      1.1
+++ regress/usr.sbin/snmpd/backend.c    28 Oct 2023 07:57:23 -0000
@@ -2633,6 +2633,173 @@ backend_getnext_toomany(void)
 }
 
 void
+backend_getnext_instance_below_region_before_instance(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid1, sessionid2;
+       struct varbind varbind[] = {
+               {
+                       .type = TYPE_NULL,
+                       .name = OID_STRUCT(MIB_BACKEND_GETNEXT, 27),
+                       .data.int32 = 1
+               },
+       };
+       struct searchrange searchrange[] = {
+               {
+                       .start = OID_STRUCT(MIB_BACKEND_GETNEXT, 27),
+                       .end = OID_STRUCT(MIB_BACKEND_GETNEXT, 27, 1, 0)
+               },
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid1 = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GETNEXT, 27, 1),
+           "backend_getnext_instance_below_region_before_instance.1");
+       sessionid2 = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GETNEXT, 27, 2),
+           "backend_getnext_instance_below_region_before_instance.2");
+       agentx_register(ax_s, sessionid1, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GETNEXT, 27), 0);
+       agentx_register(ax_s, sessionid2, 1, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GETNEXT, 27, 1, 0), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_getnext(snmp_s, community, 0, varbind, 1);
+
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       varbind[0].type = TYPE_ENDOFMIBVIEW;
+       agentx_getnext_handle(__func__, buf, n, 0, sessionid1, searchrange,
+           varbind, 1);
+       agentx_response(ax_s, buf, NOERROR, 0, varbind, 1);
+
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       varbind[0].name = searchrange[0].end;
+       varbind[0].type = TYPE_INTEGER;
+       searchrange[0].start = searchrange[0].end;
+       searchrange[0].start.include = 1;
+       searchrange[0].end.subid[searchrange[0].end.n_subid - 1]++;
+       agentx_getnext_handle(__func__, buf, n, 0, sessionid2, searchrange,
+           varbind, 1);
+       agentx_response(ax_s, buf, NOERROR, 0, varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, NOERROR, 0,
+           varbind, 1);
+}
+
+void
+backend_getnext_instance_below_region_on_instance(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid1, sessionid2;
+       struct varbind varbind[] = {
+               {
+                       .type = TYPE_NULL,
+                       .name = OID_STRUCT(MIB_BACKEND_GETNEXT, 28, 1, 0),
+                       .data.int32 = 1
+               },
+       };
+       struct searchrange searchrange[] = {
+               {
+                       .start = OID_STRUCT(MIB_BACKEND_GETNEXT, 28, 1, 1),
+                       .end = OID_STRUCT(MIB_BACKEND_GETNEXT, 29)
+               },
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid1 = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GETNEXT, 28, 1),
+           "backend_getnext_instance_below_region_on_instance.1");
+       sessionid2 = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GETNEXT, 28, 2),
+           "backend_getnext_instance_below_region_on_instance.2");
+       agentx_register(ax_s, sessionid1, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GETNEXT, 28), 0);
+       agentx_register(ax_s, sessionid2, 1, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GETNEXT, 28, 1, 0), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_getnext(snmp_s, community, 0, varbind, 1);
+
+       searchrange[0].start.include = 1;
+       varbind[0].name = searchrange[0].start;
+       varbind[0].type = TYPE_INTEGER;
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_getnext_handle(__func__, buf, n, 0, sessionid1, searchrange,
+           varbind, 1);
+       agentx_response(ax_s, buf, NOERROR, 0, varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, NOERROR, 0,
+           varbind, 1);
+}
+
+void
+backend_getnext_instance_below_region_below_instance(void)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t salen;
+       int snmp_s, ax_s;
+       uint32_t sessionid1, sessionid2;
+       struct varbind varbind[] = {
+               {
+                       .type = TYPE_NULL,
+                       .name = OID_STRUCT(MIB_BACKEND_GETNEXT, 29, 1, 0, 1),
+                       .data.int32 = 1
+               },
+       };
+       struct searchrange searchrange[] = {
+               {
+                       .start = OID_STRUCT(MIB_BACKEND_GETNEXT, 29, 1, 1),
+                       .end = OID_STRUCT(MIB_BACKEND_GETNEXT, 30)
+               },
+       };
+       int32_t requestid;
+       char buf[1024];
+       size_t n;
+
+       ax_s = agentx_connect(axsocket);
+       sessionid1 = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GETNEXT, 29, 1),
+           "backend_getnext_instance_below_region_below_instance.1");
+       sessionid2 = agentx_open(ax_s, 0, 0,
+           OID_ARG(MIB_SUBAGENT_BACKEND_GETNEXT, 29, 2),
+           "backend_getnext_instance_below_region_below_instance.2");
+       agentx_register(ax_s, sessionid1, 0, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GETNEXT, 29), 0);
+       agentx_register(ax_s, sessionid2, 1, 0, 127, 0,
+           OID_ARG(MIB_BACKEND_GETNEXT, 29, 1, 0), 0);
+
+       salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa);
+       snmp_s = snmp_connect(SOCK_DGRAM, sa, salen);
+       requestid = snmpv2_getnext(snmp_s, community, 0, varbind, 1);
+
+       searchrange[0].start.include = 1;
+       varbind[0].name = searchrange[0].start;
+       varbind[0].type = TYPE_INTEGER;
+       n = agentx_read(ax_s, buf, sizeof(buf), 1000);
+       agentx_getnext_handle(__func__, buf, n, 0, sessionid1, searchrange,
+           varbind, 1);
+       agentx_response(ax_s, buf, NOERROR, 0, varbind, 1);
+
+       snmpv2_response_validate(snmp_s, 1000, community, requestid, NOERROR, 0,
+           varbind, 1);
+}
+
+void
 backend_getbulk_nonrep_zero_maxrep_one(void)
 {
        struct sockaddr_storage ss;
Index: regress/usr.sbin/snmpd/regress.h
===================================================================
RCS file: /cvs/src/regress/usr.sbin/snmpd/regress.h,v
retrieving revision 1.2
diff -u -p -r1.2 regress.h
--- regress/usr.sbin/snmpd/regress.h    27 Oct 2023 10:26:20 -0000      1.2
+++ regress/usr.sbin/snmpd/regress.h    28 Oct 2023 07:57:23 -0000
@@ -293,6 +293,9 @@ void backend_getnext_stale(void);
 void backend_getnext_inclusive_backwards(void);
 void backend_getnext_toofew(void);
 void backend_getnext_toomany(void);
+void backend_getnext_instance_below_region_before_instance(void);
+void backend_getnext_instance_below_region_on_instance(void);
+void backend_getnext_instance_below_region_below_instance(void);
 void backend_getbulk_nonrep_zero_maxrep_one(void);
 void backend_getbulk_nonrep_zero_maxrep_two(void);
 void backend_getbulk_nonrep_one_maxrep_one(void);
Index: regress/usr.sbin/snmpd/snmpd_regress.c
===================================================================
RCS file: /cvs/src/regress/usr.sbin/snmpd/snmpd_regress.c,v
retrieving revision 1.2
diff -u -p -r1.2 snmpd_regress.c
--- regress/usr.sbin/snmpd/snmpd_regress.c      27 Oct 2023 10:26:20 -0000      
1.2
+++ regress/usr.sbin/snmpd/snmpd_regress.c      28 Oct 2023 07:57:23 -0000
@@ -143,6 +143,9 @@ const struct {
        { "backend_getnext_inclusive_backwards", 
backend_getnext_inclusive_backwards },
        { "backend_getnext_toofew", backend_getnext_toofew },
        { "backend_getnext_toomany", backend_getnext_toomany },
+       { "backend_getnext_instance_below_region_before_instance", 
backend_getnext_instance_below_region_before_instance },
+       { "backend_getnext_instance_below_region_on_instance", 
backend_getnext_instance_below_region_on_instance },
+       { "backend_getnext_instance_below_region_below_instance", 
backend_getnext_instance_below_region_below_instance },
        { "backend_getbulk_nonrep_zero_maxrep_one", 
backend_getbulk_nonrep_zero_maxrep_one },
        { "backend_getbulk_nonrep_zero_maxrep_two", 
backend_getbulk_nonrep_zero_maxrep_two },
        { "backend_getbulk_nonrep_one_maxrep_one", 
backend_getbulk_nonrep_one_maxrep_one },

Reply via email to