This is the snmpd(8) part of searchrange end issue mentioned in my libagentx diff from yesterday.[0]
Since searchranges are an agentx specific thing I implemented two cases: 1) Backends that support searchranges set ab_range to 1 (application_agentx.c) and check the av_oid_end in appl_varbind_valid. If it fails here we generate a GENERR and disconnect the backend. 2) Backends that don't support searchranges set ab_range to 0 and are not checked for overflow in appl_varbind_valid, but instead treat the response as ENDOFMIBVIEW and continue searching at av_oid_end. Since this is already the 3rd EOMV case added I decided to move to a simple variable and do the reset-logic in a single place. While here, also fix an indent in appl_close. OK? martijn@ [0] https://marc.info/?l=openbsd-tech&m=165843466721371&w=2 Index: application.c =================================================================== RCS file: /cvs/src/usr.sbin/snmpd/application.c,v retrieving revision 1.6 diff -u -p -r1.6 application.c --- application.c 30 Jun 2022 11:28:36 -0000 1.6 +++ application.c 22 Jul 2022 13:13:43 -0000 @@ -126,7 +126,7 @@ void appl_request_downstream_send(struct void appl_request_downstream_timeout(int, short, void *); void appl_request_upstream_reply(struct appl_request_upstream *); int appl_varbind_valid(struct appl_varbind *, struct appl_varbind *, int, int, - const char **); + int, const char **); int appl_varbind_backend(struct appl_varbind_internal *); void appl_varbind_error(struct appl_varbind_internal *, enum appl_error); void appl_report(struct snmp_message *, int32_t, struct ber_oid *, @@ -541,7 +541,7 @@ appl_close(struct appl_backend *backend) RB_FOREACH_SAFE(request, appl_requests, &(backend->ab_requests), trequest) - appl_request_downstream_free(request); + appl_request_downstream_free(request); } struct appl_region * @@ -1025,14 +1025,13 @@ appl_response(struct appl_backend *backe { struct appl_request_downstream *dreq, search; struct appl_request_upstream *ureq = NULL; - struct appl_region *nregion; const char *errstr; char oidbuf[1024]; enum snmp_pdutype pdutype; struct appl_varbind *vb; struct appl_varbind_internal *origvb = NULL; int invalid = 0; - int next = 0; + int next = 0, eomv; int32_t i; appl_pdu_log(backend, SNMP_C_RESPONSE, requestid, error, index, vblist); @@ -1055,7 +1054,7 @@ appl_response(struct appl_backend *backe for (i = 1; vb != NULL; vb = vb->av_next, i++) { if (!appl_varbind_valid(vb, origvb == NULL ? NULL : &(origvb->avi_varbind), next, - error != APPL_ERROR_NOERROR, &errstr)) { + error != APPL_ERROR_NOERROR, backend->ab_range, &errstr)) { smi_oid2string(&(vb->av_oid), oidbuf, sizeof(oidbuf), 0); log_warnx("%s: %"PRIu32" %s: %s", @@ -1068,35 +1067,36 @@ appl_response(struct appl_backend *backe appl_varbind_error(origvb, error); origvb->avi_state = APPL_VBSTATE_DONE; origvb->avi_varbind.av_oid = vb->av_oid; - if (vb->av_value != NULL && + + eomv = vb->av_value != NULL && vb->av_value->be_class == BER_CLASS_CONTEXT && - vb->av_value->be_type == APPL_EXC_ENDOFMIBVIEW) { - nregion = appl_region_next(ureq->aru_ctx, - &(vb->av_oid), origvb->avi_region); - if (nregion != NULL) { - ober_free_elements(vb->av_value); - origvb->avi_varbind.av_oid = - nregion->ar_oid; - origvb->avi_varbind.av_include = 1; - vb->av_value = NULL; - origvb->avi_state = APPL_VBSTATE_NEW; - } - } + vb->av_value->be_type == APPL_EXC_ENDOFMIBVIEW; + /* + * Treat results past av_oid_end for backends that + * don't support searchranges as EOMV + */ + eomv |= !backend->ab_range && next && + ober_oid_cmp(&(vb->av_oid), + &(origvb->avi_varbind.av_oid_end)) > 0; /* RFC 3584 section 4.2.2.1 */ if (ureq->aru_pduversion == SNMP_V1 && vb->av_value != NULL && vb->av_value->be_class == BER_CLASS_APPLICATION && vb->av_value->be_type == SNMP_COUNTER64) { - if (ureq->aru_pdu->be_type == SNMP_C_GETREQ) { + if (next) + eomv = 1; + else appl_varbind_error(origvb, APPL_ERROR_NOSUCHNAME); - } else { - ober_free_elements(vb->av_value); - vb->av_value = NULL; - origvb->avi_varbind.av_oid = vb->av_oid; - origvb->avi_varbind.av_include = 0; - origvb->avi_state = APPL_VBSTATE_NEW; - } + } + + if (eomv) { + ober_free_elements(vb->av_value); + origvb->avi_varbind.av_oid = + origvb->avi_varbind.av_oid_end; + origvb->avi_varbind.av_include = 1; + vb->av_value = NULL; + origvb->avi_state = APPL_VBSTATE_NEW; } origvb->avi_varbind.av_value = vb->av_value; if (origvb->avi_varbind.av_next == NULL && @@ -1150,7 +1150,7 @@ appl_response(struct appl_backend *backe int appl_varbind_valid(struct appl_varbind *varbind, struct appl_varbind *request, - int next, int null, const char **errstr) + int next, int null, int range, const char **errstr) { int cmp; int eomv = 0; @@ -1244,6 +1244,11 @@ appl_varbind_valid(struct appl_varbind * *errstr = "oid not incrementing"; return 0; } + } + if (range && ober_oid_cmp(&(varbind->av_oid), + &(request->av_oid_end)) > 0) { + *errstr = "end oid not honoured"; + return 0; } } else { if (cmp != 0) { Index: application.h =================================================================== RCS file: /cvs/src/usr.sbin/snmpd/application.h,v retrieving revision 1.2 diff -u -p -r1.2 application.h --- application.h 30 Jun 2022 11:28:36 -0000 1.2 +++ application.h 22 Jul 2022 13:13:43 -0000 @@ -109,6 +109,7 @@ struct appl_backend { char *ab_name; void *ab_cookie; uint8_t ab_retries; + int ab_range; /* Supports searchrange */ struct appl_backend_functions *ab_fn; /* * Only store downstream requests: they reference upstream and when