Right now (un)registering a region with range_subid set to !0 will
fail. Apparently nothing in the wild uses this, but let's fix it.
This is the unregister part.
OK? martijn@
diff --git a/application.c b/application.c
index f8709b8..e780025 100644
--- a/application.c
+++ b/application.c
@@ -115,6 +115,8 @@ struct snmp_target_mib {
enum appl_error appl_region(struct appl_context *, uint32_t, uint8_t,
struct ber_oid *, int, int, struct appl_backend *);
void appl_region_free(struct appl_context *, struct appl_region *);
+enum appl_error appl_region_unregister_match(struct appl_context *, uint8_t,
+ struct ber_oid *, char *, struct appl_backend *, int);
struct appl_region *appl_region_find(struct appl_context *,
const struct ber_oid *);
struct appl_region *appl_region_next(struct appl_context *,
@@ -400,9 +402,10 @@ enum appl_error
appl_unregister(const char *ctxname, uint8_t priority, struct ber_oid *oid,
uint8_t range_subid, uint32_t upper_bound, struct appl_backend *backend)
{
- struct appl_region *region, search;
struct appl_context *ctx;
char oidbuf[1024], subidbuf[11];
+ enum appl_error error;
+ uint32_t lower_bound;
size_t i;
oidbuf[0] = '\0';
@@ -444,34 +447,45 @@ appl_unregister(const char *ctxname, uint8_t priority,
struct ber_oid *oid,
return APPL_ERROR_PARSEERROR;
}
- if (range_subid > oid->bo_n) {
+ if (range_subid == 0)
+ return appl_region_unregister_match(ctx, priority, oid, oidbuf,
+ backend, 1);
+
+ range_subid--;
+ if (range_subid >= oid->bo_n) {
log_warnx("%s: Can't unregiser %s: range_subid too large",
backend->ab_name, oidbuf);
return APPL_ERROR_PARSEERROR;
}
- if (range_subid != 0 && oid->bo_id[range_subid] >= upper_bound) {
- log_warnx("%s: Can't unregister %s: upper bound smaller or "
- "equal to range_subid", backend->ab_name, oidbuf);
+ if (oid->bo_id[range_subid] > upper_bound) {
+ log_warnx("%s: Can't unregister %s: upper bound smaller than "
+ "range_subid", backend->ab_name, oidbuf);
return APPL_ERROR_PARSEERROR;
}
+ lower_bound = oid->bo_id[range_subid];
+ do {
+ if ((error = appl_region_unregister_match(ctx, priority, oid,
+ oidbuf, backend, 0)) != APPL_ERROR_NOERROR)
+ return error;
+ } while (oid->bo_id[range_subid]++ != upper_bound);
+
+ oid->bo_id[range_subid] = lower_bound;
+ do {
+ (void)appl_region_unregister_match(ctx, priority, oid, oidbuf,
+ backend, 1);
+ } while (oid->bo_id[range_subid]++ != upper_bound);
+
+ return APPL_ERROR_NOERROR;
+}
+
+enum appl_error
+appl_region_unregister_match(struct appl_context *ctx, uint8_t priority,
+ struct ber_oid *oid, char *oidbuf, struct appl_backend *backend, int
dofree)
+{
+ struct appl_region *region, search;
+
search.ar_oid = *oid;
- while (range_subid != 0 &&
- search.ar_oid.bo_id[range_subid] != upper_bound) {
- region = RB_FIND(appl_regions, &(ctx->ac_regions), &search);
- while (region != NULL && region->ar_priority < priority)
- region = region->ar_next;
- if (region == NULL || region->ar_priority != priority) {
- log_warnx("%s: Can't unregister %s: region not found",
- backend->ab_name, oidbuf);
- return APPL_ERROR_UNKNOWNREGISTRATION;
- }
- if (region->ar_backend != backend) {
- log_warnx("%s: Can't unregister %s: region not owned "
- "by backend", backend->ab_name, oidbuf);
- return APPL_ERROR_UNKNOWNREGISTRATION;
- }
- }
region = RB_FIND(appl_regions, &(ctx->ac_regions), &search);
while (region != NULL && region->ar_priority < priority)
region = region->ar_next;
@@ -485,20 +499,8 @@ appl_unregister(const char *ctxname, uint8_t priority,
struct ber_oid *oid,
"by backend", backend->ab_name, oidbuf);
return APPL_ERROR_UNKNOWNREGISTRATION;
}
-
- search.ar_oid = *oid;
- while (range_subid != 0 &&
- search.ar_oid.bo_id[range_subid] != upper_bound) {
- region = RB_FIND(appl_regions, &(ctx->ac_regions), &search);
- while (region != NULL && region->ar_priority != priority)
- region = region->ar_next;
+ if (dofree)
appl_region_free(ctx, region);
- }
- region = RB_FIND(appl_regions, &(ctx->ac_regions), &search);
- while (region != NULL && region->ar_priority != priority)
- region = region->ar_next;
- appl_region_free(ctx, region);
-
return APPL_ERROR_NOERROR;
}