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 },