This diff I'm least convinced about, but I do want to put it out there.
As far as I'm aware RFC2741 places no restrictions on direct mapping of
unregistrations on registrations. Meaning that if I register
1.3.6.1.2.[1-10] and I just unregister 1.3.6.1.2.5 this should leave
1.3.6.1.2.[1-4] and 1.3.6.1.2.[6-10] and this is what currently is
implemented (assuming previous (un)register diffs).
However, RFC2742 specifies AgentxRegistrationEntry, which presents
the the data as presented in the agentx-register-pdu. This implies
that an unregister is expected to be an exact counterpart to
agentx-register-pdu, because else an AgentxRegistrationEntry would
need to be split up, which would be a horror-show.
Do we want to add this restriction and keep the road open to
AGENTX-MIB support? Since range support is currently broken anyway
this won't cause any problems.
Thoughts? OK?
martijn@
diff --git a/application_agentx.c b/application_agentx.c
index 79900d6..60dc4df 100644
--- a/application_agentx.c
+++ b/application_agentx.c
@@ -70,11 +70,28 @@ struct appl_agentx_session {
struct ax_oid sess_oid;
struct ax_ostring sess_descr;
struct appl_backend sess_backend;
+ TAILQ_HEAD(, appl_agentx_registration) sess_registrations;
RB_ENTRY(appl_agentx_session) sess_entry;
TAILQ_ENTRY(appl_agentx_session) sess_conn_entry;
};
+/* RFC2742: AGENTX-MIB:AgentxRegistrationEntry */
+struct appl_agentx_registration {
+ uint32_t reg_index;
+ char reg_context[APPL_CONTEXTNAME_MAX + 1];
+ struct ax_oid reg_start;
+ uint8_t reg_rangesubid;
+ uint32_t reg_upperbound;
+ uint8_t reg_priority;
+ uint8_t reg_timeout;
+ uint8_t reg_instance;
+
+ struct appl_agentx_session *reg_session;
+
+ TAILQ_ENTRY(appl_agentx_registration) reg_entry;
+};
+
void appl_agentx_listen(struct agentx_master *);
void appl_agentx_accept(int, short, void *);
void appl_agentx_free(struct appl_agentx_connection *, enum appl_close_reason);
@@ -106,6 +123,7 @@ struct appl_backend_functions appl_agentx_functions = {
.ab_getnext = appl_agentx_getnext,
.ab_getbulk = NULL, /* not properly supported in application.c and
libagentx */
};
+static uint32_t appl_agentx_reg_index = 1;
RB_HEAD(appl_agentx_conns, appl_agentx_connection) appl_agentx_conns =
RB_INITIALIZER(&appl_agentx_conns);
@@ -477,6 +495,7 @@ appl_agentx_open(struct appl_agentx_connection *conn,
struct ax_pdu *pdu)
goto fail;
}
session->sess_descr.aos_string = NULL;
+ TAILQ_INIT(&(session->sess_registrations));
session->sess_conn = conn;
if (pdu->ap_header.aph_flags & AX_PDU_FLAG_NETWORK_BYTE_ORDER)
@@ -624,6 +643,12 @@ void
appl_agentx_session_free(struct appl_agentx_session *session)
{
struct appl_agentx_connection *conn = session->sess_conn;
+ struct appl_agentx_registration *reg;
+
+ while ((reg = TAILQ_FIRST(&(session->sess_registrations))) != NULL) {
+ TAILQ_REMOVE(&(session->sess_registrations), reg, reg_entry);
+ free(reg);
+ }
appl_close(&(session->sess_backend));
@@ -642,6 +667,7 @@ appl_agentx_register(struct appl_agentx_session *session,
struct ax_pdu *pdu)
struct ber_oid oid;
enum appl_error error;
int subtree = 0;
+ struct appl_agentx_registration *reg;
timeout = pdu->ap_payload.ap_register.ap_timeout;
timeout = timeout != 0 ? timeout : session->sess_timeout != 0 ?
@@ -660,6 +686,13 @@ appl_agentx_register(struct appl_agentx_session *session,
struct ax_pdu *pdu)
goto fail;
}
+ if ((reg = malloc(sizeof(*reg))) == NULL) {
+ log_warn("%s: Failed to register",
+ session->sess_backend.ab_name);
+ error = APPL_ERROR_PROCESSINGERROR;
+ goto fail;
+ }
+
error = appl_register(pdu->ap_context.aos_string, timeout,
pdu->ap_payload.ap_register.ap_priority, &oid,
pdu->ap_header.aph_flags & AX_PDU_FLAG_INSTANCE_REGISTRATION,
@@ -667,6 +700,26 @@ appl_agentx_register(struct appl_agentx_session *session,
struct ax_pdu *pdu)
pdu->ap_payload.ap_register.ap_upper_bound,
&(session->sess_backend));
+ if (error == APPL_ERROR_NOERROR) {
+ reg->reg_index = appl_agentx_reg_index++;
+ (void)strlcpy(reg->reg_context, pdu->ap_context.aos_slen == 0 ?
+ "" : (const char *)pdu->ap_context.aos_string,
+ sizeof(reg->reg_context));
+ reg->reg_start = pdu->ap_payload.ap_register.ap_subtree;
+ reg->reg_rangesubid =
+ pdu->ap_payload.ap_register.ap_range_subid;
+ reg->reg_upperbound =
+ pdu->ap_payload.ap_register.ap_upper_bound;
+ reg->reg_priority = pdu->ap_payload.ap_register.ap_priority;
+ reg->reg_timeout = pdu->ap_payload.ap_register.ap_timeout;
+ reg->reg_instance = pdu->ap_header.aph_flags &
+ AX_PDU_FLAG_INSTANCE_REGISTRATION;
+ reg->reg_session = session;
+ TAILQ_INSERT_TAIL(&(session->sess_registrations),
+ reg, reg_entry);
+ } else
+ free(reg);
+
fail:
ax_response(session->sess_conn->conn_ax, session->sess_id,
pdu->ap_header.aph_transactionid, pdu->ap_header.aph_packetid,
@@ -679,6 +732,11 @@ appl_agentx_unregister(struct appl_agentx_session
*session, struct ax_pdu *pdu)
{
struct ber_oid oid;
enum appl_error error;
+ const char *context;
+ char oidbuf[1024], subidbuf[11];
+ struct appl_agentx_registration *reg;
+ struct ax_pdu_unregister *payload = &(pdu->ap_payload.ap_unregister);
+ size_t i;
if (appl_agentx_oid2ber_oid(
&(pdu->ap_payload.ap_unregister.ap_subtree), &oid) == NULL) {
@@ -688,12 +746,58 @@ appl_agentx_unregister(struct appl_agentx_session
*session, struct ax_pdu *pdu)
goto fail;
}
+ /*
+ * Special case to keep RFC2742: AGENTX-MIB:AgentxRegistrationEntry
+ * consistent. Duplicate log warnings from appl_unregister(), while we
+ * can't enter that function.
+ */
+ context = pdu->ap_context.aos_slen == 0 ?
+ "" : (const char *)pdu->ap_context.aos_string;
+ TAILQ_FOREACH(reg, &(session->sess_registrations), reg_entry) {
+ if (strcmp(reg->reg_context, context) == 0 &&
+ ax_oid_cmp(&(reg->reg_start),
+ &(payload->ap_subtree)) == 0 &&
+ reg->reg_rangesubid == payload->ap_range_subid &&
+ reg->reg_upperbound == payload->ap_upper_bound &&
+ reg->reg_priority == payload->ap_priority)
+ break;
+ }
+ if (reg == NULL) {
+ oidbuf[0] = '\0';
+ for (i = 0; i < oid.bo_n; i++) {
+ snprintf(subidbuf, sizeof(subidbuf), "%"PRIu32,
+ oid.bo_id[i]);
+ if (i != 0)
+ strlcat(oidbuf, ".", sizeof(oidbuf));
+ if (payload->ap_range_subid == i + 1) {
+ strlcat(oidbuf, "[", sizeof(oidbuf));
+ strlcat(oidbuf, subidbuf, sizeof(oidbuf));
+ strlcat(oidbuf, "-", sizeof(oidbuf));
+ snprintf(subidbuf, sizeof(subidbuf), "%"PRIu32,
+ payload->ap_upper_bound);
+ strlcat(oidbuf, subidbuf, sizeof(oidbuf));
+ strlcat(oidbuf, "]", sizeof(oidbuf));
+ } else
+ strlcat(oidbuf, subidbuf, sizeof(oidbuf));
+ }
+ log_info("%s: Unregistering %s context(%s) priority(%"PRIu8")",
+ session->sess_backend.ab_name, oidbuf, context,
+ payload->ap_priority);
+ log_warnx("%s: Can't unregister %s: region not found",
+ session->sess_backend.ab_name, oidbuf);
+
+ error = APPL_ERROR_UNKNOWNREGISTRATION;
+ goto fail;
+ }
+
error = appl_unregister(pdu->ap_context.aos_string,
- pdu->ap_payload.ap_unregister.ap_priority, &oid,
- pdu->ap_payload.ap_unregister.ap_range_subid,
- pdu->ap_payload.ap_unregister.ap_upper_bound,
- &(session->sess_backend));
+ payload->ap_priority, &oid, payload->ap_range_subid,
+ payload->ap_upper_bound, &(session->sess_backend));
+ if (error == APPL_ERROR_NOERROR) {
+ TAILQ_REMOVE(&(session->sess_registrations), reg, reg_entry);
+ free(reg);
+ }
fail:
ax_response(session->sess_conn->conn_ax, session->sess_id,
pdu->ap_header.aph_transactionid, pdu->ap_header.aph_packetid,