From dd8d706e1b67d1838582a3fd37e167740697e20d Mon Sep 17 00:00:00 2001 From: Vojtech Vilimek Date: Sat, 10 Aug 2024 00:07:49 +0200 Subject: [PATCH] SNMP: tmp -- fix byte order handling --- proto/snmp/bgp4_mib.c | 27 ++--- proto/snmp/mib_tree.c | 74 ++++++------- proto/snmp/snmp.c | 4 +- proto/snmp/snmp_test.c | 52 ++++----- proto/snmp/snmp_utils.c | 235 +++++++++++++++++----------------------- proto/snmp/snmp_utils.h | 8 +- proto/snmp/subagent.c | 162 ++++++++++++++++----------- proto/snmp/subagent.h | 40 +++---- 8 files changed, 294 insertions(+), 308 deletions(-) diff --git a/proto/snmp/bgp4_mib.c b/proto/snmp/bgp4_mib.c index 9a0418fd..d81d0432 100644 --- a/proto/snmp/bgp4_mib.c +++ b/proto/snmp/bgp4_mib.c @@ -245,6 +245,7 @@ snmp_bgp4_register(struct snmp_proto *p) struct oid *oid = mb_allocz(p->pool, snmp_oid_size_from_len(ARRAY_SIZE(bgp_mib_prefix))); + print(; STORE_U8(oid->n_subid, ARRAY_SIZE(bgp_mib_prefix)); STORE_U8(oid->prefix, SNMP_MGMT); @@ -284,10 +285,10 @@ ip4_to_oid(struct oid *o, ip4_addr addr) { u32 tmp = ip4_to_u32(addr); ASSUME(o->n_subid >= 9); - STORE_U32(o->ids[5], (tmp & 0xFF000000) >> 24); - STORE_U32(o->ids[6], (tmp & 0x00FF0000) >> 16); - STORE_U32(o->ids[7], (tmp & 0x0000FF00) >> 8); - STORE_U32(o->ids[8], (tmp & 0x000000FF) >> 0); + o->ids[5] = (tmp & 0xFF000000) >> 24; + o->ids[6] = (tmp & 0x00FF0000) >> 16; + o->ids[7] = (tmp & 0x0000FF00) >> 8; + o->ids[8] = (tmp & 0x000000FF) >> 0; } static void UNUSED @@ -337,7 +338,7 @@ populate_bgp4(struct snmp_pdu *c, ip4_addr *addr, const struct bgp_proto **proto **conn, const struct bgp_stats **stats, const struct bgp_config **config) { const struct oid * const oid = &c->sr_vb_start->name; - if (snmp_bgp_valid_ip4(oid) && LOAD_U8(oid->n_subid) == 9) + if (snmp_bgp_valid_ip4(oid) && oid->n_subid == 9) *addr = ip4_from_oid(oid); else return SNMP_SEARCH_NO_INSTANCE; @@ -378,7 +379,7 @@ populate_bgp4(struct snmp_pdu *c, ip4_addr *addr, const struct bgp_proto **proto static enum snmp_search_res fill_bgp_version(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c) { - if (LOAD_U8(c->sr_vb_start->name.n_subid) != 3) + if (c->sr_vb_start->name.n_subid != 3) return SNMP_SEARCH_NO_INSTANCE; c->size -= snmp_str_size_from_len(1); snmp_varbind_nstr(c, BGP4_VERSIONS, 1); @@ -388,7 +389,7 @@ fill_bgp_version(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c) static enum snmp_search_res fill_local_as(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c) { - if (LOAD_U8(c->sr_vb_start->name.n_subid) != 3) + if (c->sr_vb_start->name.n_subid != 3) return SNMP_SEARCH_NO_INSTANCE; snmp_varbind_int(c, c->p->bgp_local_as); return SNMP_SEARCH_OK; @@ -743,7 +744,7 @@ fill_in_update_elapsed_time(struct mib_walk_state *walk UNUSED, struct snmp_pdu static enum snmp_search_res fill_local_id(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c) { - if (LOAD_U8(c->sr_vb_start->name.n_subid) != 3) + if (c->sr_vb_start->name.n_subid != 3) return SNMP_SEARCH_NO_INSTANCE; snmp_varbind_ip4(c, c->p->bgp_local_id); return SNMP_SEARCH_OK; @@ -771,10 +772,10 @@ bgp4_next_peer(struct mib_walk_state *state, struct snmp_pdu *c) const struct oid *peer_oid = (const struct oid *) &bgp4_peer_id; int precise = 1; - if (LOAD_U8(oid->n_subid) > 9) + if (oid->n_subid > 9) precise = 0; - if (LOAD_U8(oid->n_subid) != 9 || snmp_oid_compare(oid, peer_oid) < 0) + if (oid->n_subid != 9 || snmp_oid_compare(oid, peer_oid) < 0) { int old = snmp_oid_size(oid); int new = snmp_oid_size(peer_oid); @@ -785,7 +786,7 @@ bgp4_next_peer(struct mib_walk_state *state, struct snmp_pdu *c) c->buffer += (new - old); snmp_oid_copy(oid, peer_oid); - STORE_U8(oid->include, 1); + oid->include = 1; } ASSUME(oid->n_subid == 9); @@ -799,9 +800,9 @@ bgp4_next_peer(struct mib_walk_state *state, struct snmp_pdu *c) int match = trie_walk_init(&ws, c->p->bgp_trie, &net, 1); - if (match && LOAD_U8(oid->include) && precise) + if (match && oid->include && precise) { - STORE_U8(oid->include, 0); + oid->include = 0; ip4_to_oid(oid, ip4); return 0; } diff --git a/proto/snmp/mib_tree.c b/proto/snmp/mib_tree.c index af0b7c09..23fcdfc5 100644 --- a/proto/snmp/mib_tree.c +++ b/proto/snmp/mib_tree.c @@ -46,13 +46,13 @@ mib_tree_init(pool *p, struct mib_tree *t) struct oid *oid = tmp_alloc( snmp_oid_size_from_len((uint) ARRAY_SIZE(snmp_internet))); - STORE_U8(oid->n_subid, ARRAY_SIZE(snmp_internet)); - STORE_U8(oid->prefix, 0); - STORE_U8(oid->include, 0); - STORE_U8(oid->reserved, 0); + oid->n_subid = ARRAY_SIZE(snmp_internet); + oid->prefix = 0; + oid->include = 0; + oid->reserved = 0; for (size_t i = 0; i < ARRAY_SIZE(snmp_internet); i++) - STORE_U32(oid->ids[i], snmp_internet[i]); + oid->ids[i] = snmp_internet[i]; (void) mib_tree_add(p, t, oid, 0); } @@ -110,7 +110,7 @@ mib_tree_add(pool *p, struct mib_tree *t, const struct oid *oid, int is_leaf) mib_tree_walk_init(&walk, t); node = mib_tree_find(t, &walk, oid); - ASSERT(walk.id_pos <= LOAD_U8(oid->n_subid) + 1); + ASSERT(walk.id_pos <= oid->n_subid + 1); if (node) { @@ -122,7 +122,7 @@ mib_tree_add(pool *p, struct mib_tree *t, const struct oid *oid, int is_leaf) return NULL; } - ASSERT(walk.id_pos < LOAD_U8(oid->n_subid) + 1); + ASSERT(walk.id_pos < oid->n_subid + 1); node = walk.stack[walk.stack_pos - 1]; /* we encounter leaf node before end of OID's id path */ @@ -161,14 +161,14 @@ mib_tree_add(pool *p, struct mib_tree *t, const struct oid *oid, int is_leaf) if (walk.stack_pos == ARRAY_SIZE(snmp_internet) + 1) { u32 old_len = node_inner->child_len; - node_inner->child_len = MAX(old_len, (u32) LOAD_U8(oid->prefix) + 1); + node_inner->child_len = MAX(old_len, (u32) oid->prefix + 1); node_inner->children = realloc(node_inner->children, node_inner->child_len * sizeof(mib_node_u *)); for (u32 i = old_len; i < node_inner->child_len; i++) node_inner->children[i] = NULL; - if (is_leaf && !LOAD_U8(oid->n_subid)) + if (is_leaf && !oid->n_subid) { node = allocz(sizeof(struct mib_leaf)); node->empty.flags = MIB_TREE_LEAF; @@ -179,9 +179,9 @@ mib_tree_add(pool *p, struct mib_tree *t, const struct oid *oid, int is_leaf) node->empty.flags = 0; } - node->empty.id = LOAD_U8(oid->prefix); + node->empty.id = oid->prefix; /* add node into the parent's children array */ - node_inner->children[LOAD_U8(oid->prefix)] = node; + node_inner->children[oid->prefix] = node; node_inner = &node->inner; walk.stack[walk.stack_pos++] = node; } @@ -190,17 +190,17 @@ mib_tree_add(pool *p, struct mib_tree *t, const struct oid *oid, int is_leaf) /* snmp_internet + 2 = empty + snmp_internet + prefix */ if (snmp_oid_is_prefixed(oid) && walk.stack_pos == ARRAY_SIZE(snmp_internet) + 2 && - LOAD_U8(oid->n_subid) == 0 && + oid->n_subid == 0 && mib_node_is_leaf(node) == is_leaf) return node; if (mib_node_is_leaf(node)) return node; - u8 subids = LOAD_U8(oid->n_subid); + u8 subids = oid->n_subid; u32 old_len = node_inner->child_len; u32 child_id = oid->ids[walk.id_pos]; - node_inner->child_len = MAX(old_len, LOAD_U32(child_id) + 1); + node_inner->child_len = MAX(old_len, child_id + 1); node_inner->children = realloc(node_inner->children, node_inner->child_len * sizeof(mib_node_u *)); @@ -217,7 +217,7 @@ mib_tree_add(pool *p, struct mib_tree *t, const struct oid *oid, int is_leaf) parent->children[child_id] = (mib_node_u *) node_inner; node_inner->c.id = child_id; - child_id = LOAD_U32(oid->ids[++walk.id_pos]); + child_id = oid->ids[++walk.id_pos]; node_inner->child_len = child_id + 1; node_inner->children = allocz(node_inner->child_len * sizeof(mib_node_u *)); @@ -430,14 +430,14 @@ mib_tree_find(const struct mib_tree *t, struct mib_walk_state *walk, const struc /* In any of cases below we did not move in the tree therefore the * walk->id_pos is left untouched. */ if (snmp_oid_is_prefixed(oid) && - LOAD_U8(oid->n_subid) + ARRAY_SIZE(snmp_internet) + 1 == walk->id_pos) + oid->n_subid + ARRAY_SIZE(snmp_internet) + 1 == walk->id_pos) return node; else if (snmp_oid_is_prefixed(oid) && - LOAD_U8(oid->n_subid) + ARRAY_SIZE(snmp_internet) + 1 > walk->id_pos) + oid->n_subid + ARRAY_SIZE(snmp_internet) + 1 > walk->id_pos) return NULL; - else if (!snmp_oid_is_prefixed(oid) && LOAD_U8(oid->n_subid) + 1 == walk->id_pos) + else if (!snmp_oid_is_prefixed(oid) && oid->n_subid + 1 == walk->id_pos) return node; } @@ -470,7 +470,7 @@ mib_tree_find(const struct mib_tree *t, struct mib_walk_state *walk, const struc } /* walking the prefix continuation (OID field oid->prefix) */ - u8 prefix = LOAD_U8(oid->prefix); + u8 prefix = oid->prefix; if (node_inner->child_len <= prefix) return NULL; @@ -483,18 +483,18 @@ mib_tree_find(const struct mib_tree *t, struct mib_walk_state *walk, const struc ASSERT(node->empty.id == prefix); walk->stack[walk->stack_pos++] = node; - if (mib_node_is_leaf(node) && LOAD_U8(oid->n_subid) > 0) + if (mib_node_is_leaf(node) && oid->n_subid > 0) return NULL; } - u8 subids = LOAD_U8(oid->n_subid); + u8 subids = oid->n_subid; if (subids == 0) return (node == (mib_node_u *) &t->root) ? NULL : node; /* loop for all OID's ids except the last one */ for (; oid_pos < subids - 1 && walk->stack_pos < MIB_WALK_STACK_SIZE + 1; oid_pos++) { - u32 id = LOAD_U32(oid->ids[oid_pos]); + u32 id = oid->ids[oid_pos]; if (node_inner->child_len <= id) { /* The walk->id_pos points after the last accepted OID id. @@ -527,7 +527,7 @@ mib_tree_find(const struct mib_tree *t, struct mib_walk_state *walk, const struc } walk->id_pos = oid_pos; - u32 last_id = LOAD_U32(oid->ids[oid_pos]); + u32 last_id = oid->ids[oid_pos]; if (node_inner->child_len <= last_id || walk->stack_pos >= MIB_WALK_STACK_SIZE + 1) return NULL; @@ -598,9 +598,9 @@ mib_tree_walk_to_oid(const struct mib_walk_state *walk, struct oid *result, u32 /* skip empty prefix, whole snmp_internet .1.3.6.1 and oid->prefix */ index = 2 + ARRAY_SIZE(snmp_internet); - STORE_U8(result->n_subid, walk->stack_pos - (ARRAY_SIZE(snmp_internet) + 2)); - STORE_U8(result->prefix, - walk->stack[ARRAY_SIZE(snmp_internet) + 1]->empty.id); + result->n_subid = walk->stack_pos - (ARRAY_SIZE(snmp_internet) + 2); + result->prefix = \ + walk->stack[ARRAY_SIZE(snmp_internet) + 1]->empty.id; } else { @@ -608,17 +608,17 @@ mib_tree_walk_to_oid(const struct mib_walk_state *walk, struct oid *result, u32 return 1; index = 1; /* skip empty prefix */ - STORE_U8(result->n_subid, walk->stack_pos - 1); - STORE_U8(result->prefix, 0); + result->n_subid = walk->stack_pos - 1; + result->prefix = 0; } - STORE_U8(result->include, 0); - STORE_U8(result->reserved, 0); + result->include = 0; + result->reserved = 0; u32 i = 0; /* the index could point after last stack array element */ for (; index < walk->stack_pos && index < MIB_WALK_STACK_SIZE; index++) - STORE_U32(result->ids[i++], walk->stack[index]->empty.id); + result->ids[i++] = walk->stack[index]->empty.id; return 0; } @@ -639,9 +639,9 @@ mib_tree_walk_oid_compare(const struct mib_walk_state *walk, const struct oid *o uint walk_idx = 1; u8 walk_subids = walk->stack_pos; /* left_subids */ - u8 oid_subids = LOAD_U8(oid->n_subid); /* right_subids */ + u8 oid_subids = oid->n_subid; /* right_subids */ - const u8 oid_prefix = LOAD_U8(oid->prefix); + const u8 oid_prefix = oid->prefix; if (oid_prefix != 0) { @@ -668,7 +668,7 @@ mib_tree_walk_oid_compare(const struct mib_walk_state *walk, const struct oid *o for (; i < oid_subids && walk_idx < walk_subids; i++, walk_idx++) { u32 walk_id = walk->stack[walk_idx]->empty.id; - u32 oid_id = LOAD_U32(oid->ids[i]); + u32 oid_id = oid->ids[i]; if (walk_id < oid_id) return -1; else if (walk_id > oid_id) @@ -714,16 +714,16 @@ mib_tree_walk_is_oid_descendant(const struct mib_walk_state *walk, const struct return +1; if (i < walk->stack_pos && - walk->stack[i]->empty.id != (u32)LOAD_U8(oid->prefix)) + walk->stack[i]->empty.id != (u32) oid->prefix) return -1; i++; } - u32 ids = LOAD_U8(oid->n_subid); + u32 ids = oid->n_subid; for (; i < walk->stack_pos && j < ids; i++, j++) { - if (walk->stack[i]->empty.id != LOAD_U32(oid->ids[j])) + if (walk->stack[i]->empty.id != oid->ids[j]) return -1; } diff --git a/proto/snmp/snmp.c b/proto/snmp/snmp.c index 2200cca2..c37f4394 100644 --- a/proto/snmp/snmp.c +++ b/proto/snmp/snmp.c @@ -140,10 +140,10 @@ void agentx_get_mib_init(pool *p) struct oid *dest = mb_alloc(p, size); memcpy(dest, src, size); - u8 ids = LOAD_U8(src->n_subid); + u8 ids = src->n_subid; if (ids > 0) - STORE_U32(dest->ids[ids - 1], LOAD_U32(src->ids[ids - 1]) + 1); + dest->ids[ids - 1] = src->ids[ids - 1] + 1; agentx_available_mibs[AGENTX_MIB_COUNT] = dest; } diff --git a/proto/snmp/snmp_test.c b/proto/snmp/snmp_test.c index 1223d135..e572d886 100644 --- a/proto/snmp/snmp_test.c +++ b/proto/snmp/snmp_test.c @@ -783,17 +783,17 @@ t_walk_oid_desc(void) case 1: { /* oid is longer than walk or has same length */ - u8 ids = LOAD_U8(oid->n_subid); + u8 ids = oid->n_subid; u32 upto = MIN(OID_MAX_LEN - ids, 16); if (!upto) continue; u32 new = xrandom(upto) + 1; - STORE_U8(oid->n_subid, ids + new); + oid->n_subid = ids + new; for (u32 i = 0; i < new; i++) - STORE_U32(oid->ids[ids + i], xrandom(OID_MAX_ID)); + oid->ids[ids + i] = xrandom(OID_MAX_ID); bt_assert(mib_tree_walk_is_oid_descendant(&walk, oid) > 0); @@ -803,7 +803,7 @@ t_walk_oid_desc(void) case 3: { /* oid is shorter than walk */ - u8 ids = LOAD_U8(oid->n_subid); + u8 ids = oid->n_subid; if (ids == 0 || ids == OID_MAX_LEN) continue; @@ -811,14 +811,14 @@ t_walk_oid_desc(void) u32 split = (ids > 1) ? xrandom(ids - 1) + 1 : 0; u32 ext = (type == 3) ? xrandom(MIN(OID_MAX_LEN - ids, 16)) : 0; - STORE_U16(oid->n_subid, split + ext); + oid->n_subid = split + ext; for (u32 i = 0; i < ext; i++) - STORE_U32(oid->ids[split + i], xrandom(OID_MAX_ID)); + oid->ids[split + i] = xrandom(OID_MAX_ID); int no_change = 1; for (u32 j = 0; j < MIN(ids - split, ext); j++) { - if (LOAD_U32(oid->ids[split + j]) != LOAD_U32(oids[i]->ids[split + j])) + if (oid->ids[split + j] != oids[i]->ids[split + j]) no_change = 0; } @@ -897,18 +897,18 @@ t_walk_oid_compare(void) case 1: { /* oid is longer than walk or has same length */ - u8 ids = LOAD_U8(oid->n_subid); + u8 ids = oid->n_subid; u32 upto = MIN(OID_MAX_LEN - ids, 16); if (!upto) continue; u32 new = xrandom(upto) + 1; - STORE_U8(oid->n_subid, ids + new); + oid->n_subid = ids + new; ASSERT(snmp_oid_size(oid) < 1024); for (u32 i = 0; i < new; i++) - STORE_U32(oid->ids[ids + i], xrandom(OID_MAX_ID)); + oid->ids[ids + i] = xrandom(OID_MAX_ID); bt_assert(mib_tree_walk_oid_compare(&walk, oid) < 0); @@ -918,7 +918,7 @@ t_walk_oid_compare(void) case 3: { /* oid is shorter than walk */ - u8 ids = LOAD_U8(oid->n_subid); + u8 ids = oid->n_subid; if (ids == 0 || ids == OID_MAX_LEN) continue; @@ -926,13 +926,13 @@ t_walk_oid_compare(void) u32 split = (ids > 1) ? xrandom(ids - 1) + 1 : 0; u32 ext = (type == 3) ? xrandom(MIN(OID_MAX_LEN - ids, 16)) : 0; - STORE_U16(oid->n_subid, split + ext); + oid->n_subid = split + ext; for (u32 i = 0; i < ext; i++) - STORE_U32(oid->ids[split + i], xrandom(OID_MAX_ID)); + oid->ids[split + i] = xrandom(OID_MAX_ID); int cmp_res = 0; for (u32 j = 0; j < MIN(ids - split, ext) && !cmp_res; j++) - cmp_res = LOAD_U32(oids[i]->ids[split + j]) - LOAD_U32(oid->ids[split + j]); + cmp_res = oids[i]->ids[split + j] - oid->ids[split + j]; if (!cmp_res && split + ext == ids) continue; @@ -1256,16 +1256,16 @@ gen_test_find(struct oid *(*generator)(void)) } else { - for (uint j = 0; j < MIN(LOAD_U8(oids[i]->n_subid), + for (uint j = 0; j < MIN(oids[i]->n_subid, ARRAY_SIZE(snmp_internet)); j++) { - if (LOAD_U32(oids[i]->ids[j]) == snmp_internet[j] && + if (oids[i]->ids[j] == snmp_internet[j] && j >= longest_inet_pref_len) { longest_inet_pref->ids[j] = snmp_internet[j]; longest_inet_pref_len = j + 1; } - else if (LOAD_U32(oids[i]->ids[j]) == snmp_internet[j]) + else if (oids[i]->ids[j] == snmp_internet[j]) ; else break; @@ -1360,19 +1360,19 @@ gen_test_find(struct oid *(*generator)(void)) last = found; /* test finding with walk state not pointing at the root of the tree */ - u8 subids = LOAD_U8(oids[i]->n_subid); + u8 subids = oids[i]->n_subid; if (subids > 0) { found = NULL; u32 new_ids = xrandom(subids); mib_tree_walk_init(&walk, (xrandom(2)) ? tree : NULL); - STORE_U8(oids[i]->n_subid, new_ids); + oids[i]->n_subid = new_ids; mib_node_u *ignored UNUSED; ignored = mib_tree_find(tree, &walk, oids[i]); - STORE_U8(oids[i]->n_subid, subids); + oids[i]->n_subid = subids; found = mib_tree_find(tree, &walk, oids[i]); @@ -1410,7 +1410,7 @@ gen_test_find(struct oid *(*generator)(void)) if (!has_node && !snmp_oid_is_prefixed(oid)) { for (uint i = 0; i < MIN(ARRAY_SIZE(snmp_internet), - LOAD_U8(oid->n_subid)); i++) + oid->n_subid); i++) { if (longest_inet_pref->ids[i] != 0 && longest_inet_pref->ids[i] == oid->ids[i]) @@ -1422,7 +1422,7 @@ gen_test_find(struct oid *(*generator)(void)) } } - if (has_node && LOAD_U8(oid->n_subid) > ARRAY_SIZE(snmp_internet)) + if (has_node && oid->n_subid > ARRAY_SIZE(snmp_internet)) has_node = 0; } @@ -1437,19 +1437,19 @@ gen_test_find(struct oid *(*generator)(void)) last = found; - u8 subids = LOAD_U8(searched[search]->n_subid); + u8 subids = searched[search]->n_subid; if (subids > 0) { found = NULL; u32 new_ids = xrandom(subids); mib_tree_walk_init(&walk, (xrandom(2)) ? tree : NULL); - STORE_U8(searched[search]->n_subid, new_ids); + searched[search]->n_subid = new_ids; mib_node_u *ignored UNUSED; ignored = mib_tree_find(tree, &walk, searched[search]); - STORE_U8(searched[search]->n_subid, subids); + searched[search]->n_subid = subids; found = mib_tree_find(tree, &walk, searched[search]); @@ -1725,7 +1725,7 @@ gen_test_traverse(struct oid *(*generator)(void)) { if (snmp_oid_is_prefixed(sorted[d])) bound += 5; - bound += (int)LOAD_U8(sorted[d]->n_subid); + bound += (int) sorted[d]->n_subid; } if (!no_inet_prefix) diff --git a/proto/snmp/snmp_utils.c b/proto/snmp/snmp_utils.c index bb4bb811..a64b820e 100644 --- a/proto/snmp/snmp_utils.c +++ b/proto/snmp/snmp_utils.c @@ -46,7 +46,7 @@ inline void * snmp_varbind_data(const struct agentx_varbind *vb) { uint name_size = snmp_oid_size(&vb->name); - return (void *)&vb->name + name_size; + return (void *) &vb->name + name_size; } struct oid * @@ -54,23 +54,23 @@ snmp_varbind_set_name_len(struct snmp_pdu *c, struct agentx_varbind **vb, u8 len { struct oid *oid = &(*vb)->name; - if (LOAD_U8(oid->n_subid) >= len) + if (oid->n_subid >= len) { - c->size += (LOAD_U8(oid->n_subid) - len) * sizeof(u32); - STORE_U8(oid->n_subid, len); + c->size += (oid->n_subid - len) * sizeof(u32); + oid->n_subid = len; return oid; } /* We need more space */ - ASSUME(len >= LOAD_U8(oid->n_subid)); - uint diff_size = (len - LOAD_U8(oid->n_subid)) * sizeof(u32); + ASSUME(len >= oid->n_subid); + uint diff_size = (len - oid->n_subid) * sizeof(u32); if (snmp_tbuf_reserve(c, diff_size)) oid = &(*vb)->name; ASSERT(c->size >= diff_size); c->size -= diff_size; - STORE_U8(oid->n_subid, len); + oid->n_subid = len; return &(*vb)->name; } @@ -78,7 +78,7 @@ void snmp_varbind_duplicate_hdr(struct snmp_pdu *c, struct agentx_varbind **vb) { ASSUME(vb != NULL && *vb != NULL); - uint hdr_size = snmp_varbind_header_size(*vb); + uint hdr_size = snmp_varbind_header_size(*vb->name); (void) snmp_tbuf_reserve(c, hdr_size); ASSERT(c->size >= hdr_size); @@ -100,7 +100,7 @@ snmp_is_oid_empty(const struct oid *oid) { /* We intentionaly ignore padding that should be zeroed */ if (oid != NULL) - return LOAD_U8(oid->n_subid) == 0 && LOAD_U8(oid->prefix) == 0; + return oid->n_subid == 0 && oid->prefix == 0; else return 0; } @@ -119,10 +119,10 @@ snmp_oid_is_prefixable(const struct oid *oid) return 0; for (int i = 0; i < 4; i++) - if (LOAD_U32(oid->ids[i]) != snmp_internet[i]) + if (oid->ids[i] != snmp_internet[i]) return 0; - if (LOAD_U32(oid->ids[4]) >= 256) + if (oid->ids[4] >= 256) return 0; return 1; @@ -148,27 +148,12 @@ snmp_pkt_len(const byte *start, const byte *end) void snmp_oid_copy(struct oid *dest, const struct oid *src) { - STORE_U8(dest->n_subid, src->n_subid); - STORE_U8(dest->prefix, src->prefix); - STORE_U8(dest->include, src->include ? 1 : 0); - STORE_U8(dest->reserved, 0); - - for (int i = 0; i < LOAD_U8(src->n_subid); i++) - STORE_U32(dest->ids[i], src->ids[i]); -} - -/* this function assumes enougth space inside dest is allocated */ -void -snmp_oid_copy2(struct oid *dest, const struct oid *src) -{ - /* The STORE_U8() and LOAD_U8() cancel out */ dest->n_subid = src->n_subid; dest->prefix = src->prefix; dest->include = src->include ? 1 : 0; dest->reserved = 0; - /* The STORE_U32() and LOAD_U32 cancel out */ - memcpy(dest->ids, src->ids, LOAD_U8(src->n_subid) * sizeof(u32)); + memcpy(dest->ids, src->ids, src->n_subid * sizeof(u32)); } /* @@ -235,18 +220,21 @@ snmp_str_size(const char *str) } /** - * snmp_oid_size - measure size of oid in bytes + * snmp_oid_size - measure size of OID in bytes * @o: object identifier to use + * + * Work for both packet and cpu native byte orders. */ uint snmp_oid_size(const struct oid *o) { + /* LOAD_U8() is in both cases basic mem read */ return 4 + (LOAD_U8(o->n_subid) * 4); } -/** - * snmp_get_size - calculate size for allocation - * @n_subid: number of ids in oid +/* + * snmp_oid_size_from_len - return size of OID with @n_subid subids in bytes + * @n_subid: number of subids in ids array */ inline size_t snmp_oid_size_from_len(uint n_subid) @@ -254,19 +242,6 @@ snmp_oid_size_from_len(uint n_subid) return sizeof(struct oid) + n_subid * sizeof(u32); } -/* - * snmp_varbind_hdr_size_from_oid - return in-buffer size of VarBind - * @oid: OID used as VarBind's name - * - * This function assume @oid to be not NULL. - */ -uint -snmp_varbind_hdr_size_from_oid(const struct oid *oid) -{ - ASSUME(oid); - return snmp_oid_size(oid) + OFFSETOF(struct agentx_varbind, name); -} - /* * snmp_set_varbind_type - set VarBind's type field * @vb: Varbind inside TX buffer @@ -308,54 +283,40 @@ snmp_set_varbind_type(struct agentx_varbind *vb, enum agentx_type t) } } -/* Internal wrapper */ -static inline u16 -snmp_load_varbind_type(const struct agentx_varbind *vb) -{ - return LOAD_U16(vb->type); -} - -/* - * snmp_get_varbind_type - loads a VarBind type - * @vb: VarBind pointer to TX buffer - * - * This function assumes VarBind with valid type, always call snmp_test_varbind - * for in TX buffer VarBinds. - */ -inline enum agentx_type -snmp_get_varbind_type(const struct agentx_varbind *vb) -{ - ASSUME(snmp_test_varbind(vb)); - return (enum agentx_type) snmp_load_varbind_type(vb); -} - static inline uint snmp_get_octet_size(const struct agentx_octet_str *str) { - return LOAD_U32(str->length); + return str->length; } /** * snmp_varbind_header_size - measure size of VarBind without data in bytes - * @vb: VarBind to use + * @vb_name: VarBind OID name * * Return size including whole OID as well as the VarBind header. */ uint -snmp_varbind_header_size(const struct agentx_varbind *vb) +snmp_varbind_header_size(const struct oid *vb_name) { - return snmp_varbind_hdr_size_from_oid(&vb->name); + ASSUME(vb_name); + return snmp_oid_size(vb_name) + OFFSETOF(struct agentx_varbind, name); } +/* + * Beware that for octet string, using this function may be a bit tricky due to + * the different byte orders cpu native/packet + * + * + */ uint -snmp_varbind_size_unsafe(const struct agentx_varbind *vb) +snmp_varbind_size_unsafe(const struct agentx_varbind *vb, int is_pkt_bo) { ASSUME(snmp_test_varbind(vb)); - enum agentx_type type = snmp_get_varbind_type(vb); + enum agentx_type type = (is_pkt_bo) ? LOAD_U16(vb->type) : vb->type; int value_size = agentx_type_size(type); - uint vb_header = snmp_varbind_header_size(vb); + uint vb_header = snmp_varbind_header_size(&vb->name); if (value_size == 0) return vb_header; @@ -377,6 +338,7 @@ snmp_varbind_size_unsafe(const struct agentx_varbind *vb) default: /* Shouldn't happen */ + die("getting size of VarBind with unknown type (%u)", type); return 0; } } @@ -392,7 +354,7 @@ snmp_varbind_size_unsafe(const struct agentx_varbind *vb) uint snmp_varbind_size(const struct agentx_varbind *vb, uint limit) { - ASSUME(snmp_test_varbind(vb)); + //ASSUME(snmp_test_varbind(vb)); if (limit < sizeof(struct agentx_varbind)) return 0; @@ -457,15 +419,12 @@ snmp_varbind_size_from_len(uint n_subid, enum agentx_type type, uint len) } /* - * snmp_test_varbind - test validity of VarBind's type - * @vb: VarBind to test + * snmp_test_varbind - test validity of VarBind type + * @type: Type of VarBind */ int -snmp_test_varbind(const struct agentx_varbind *vb) +snmp_test_varbind(u16 type) { - ASSUME(vb); - - u16 type = snmp_load_varbind_type(vb); if (type == AGENTX_INTEGER || type == AGENTX_OCTET_STRING || type == AGENTX_NULL || @@ -506,7 +465,6 @@ struct agentx_varbind * snmp_create_varbind(byte *buf, struct oid *oid) { struct agentx_varbind *vb = (void *) buf; - STORE_U16(vb->reserved, 0); snmp_oid_copy(&vb->name, oid); return vb; } @@ -519,7 +477,7 @@ snmp_create_varbind(byte *buf, struct oid *oid) int snmp_valid_ip4_index(const struct oid *o, uint start) { - if (start + 3 < LOAD_U8(o->n_subid)) + if (start + 3 < o->n_subid) return snmp_valid_ip4_index_unsafe(o, start); else return 0; @@ -537,7 +495,7 @@ int snmp_valid_ip4_index_unsafe(const struct oid *o, uint start) { for (int i = 0; i < 4; i++) - if (LOAD_U32(o->ids[start + i]) >= 256) + if (o->ids[start + i] >= 256) return 0; return 1; @@ -561,7 +519,7 @@ snmp_put_nstr(byte *buf, const char *str, uint len) /* Insert zero padding in the gap at the end */ for (uint i = 0; i < alen - len; i++) - STORE_U8(buf[i], '\0'); + buf[i] = '\0'; return buf + (alen - len); } @@ -602,19 +560,6 @@ snmp_put_blank(byte *buf) return buf + 4; } -/** - * snmp_put_oid - put oid into SNMP PDU transcieve buffer - * @buf: pointer to first free buffer byte - * @oid: object identifier to use - */ -byte * -snmp_put_oid(byte *buf, struct oid *oid) -{ - struct oid *oid_buf = (void *) buf; - snmp_oid_copy(oid_buf, oid); - return buf + snmp_oid_size(oid); -} - /** * snmp_put_fbyte - put one padded byte to SNMP PDU transcieve buffer * @buf: pointer to free buffer byte @@ -642,10 +587,10 @@ void snmp_oid_ip4_index(struct oid *o, uint start, ip4_addr addr) { u32 temp = ip4_to_u32(addr); - STORE_U32(o->ids[start], temp >> 24); - STORE_U32(o->ids[start + 1], (temp >> 16) & 0xFF); - STORE_U32(o->ids[start + 2], (temp >> 8) & 0xFF); - STORE_U32(o->ids[start + 3], temp & 0xFF); + o->ids[start] = temp >> 24; + o->ids[start + 1] = (temp >> 16) & 0xFF; + o->ids[start + 2] = (temp >> 8) & 0xFF; + o->ids[start + 3] = temp & 0xFF; } @@ -662,11 +607,11 @@ snmp_oid_ip4_index(struct oid *o, uint start, ip4_addr addr) int snmp_oid_compare(const struct oid *left, const struct oid *right) { - const u8 left_subids = LOAD_U8(left->n_subid); - u8 right_subids = LOAD_U8(right->n_subid); /* see hack for more info */ + const u8 left_subids = left->n_subid; + u8 right_subids = right->n_subid; /* see hack for more info */ - const u8 left_prefix = LOAD_U8(left->prefix); - const u8 right_prefix = LOAD_U8(right->prefix); + const u8 left_prefix = left->prefix; + const u8 right_prefix = right->prefix; if (left_prefix == 0 && right_prefix == 0) goto test_ids; @@ -679,7 +624,7 @@ snmp_oid_compare(const struct oid *left, const struct oid *right) uint bound = MIN((uint) left_subids, (uint) ARRAY_SIZE(snmp_internet)); for (uint idx = 0; idx < bound; idx++) { - u32 id = LOAD_U32(left->ids[idx]); + u32 id = left->ids[idx]; if (id < snmp_internet[idx]) return -1; else if (id > snmp_internet[idx]) @@ -690,9 +635,9 @@ snmp_oid_compare(const struct oid *left, const struct oid *right) return -1; /* check prefix */ - if (LOAD_U32(left->ids[4]) < (u32) right_prefix) + if (left->ids[4] < (u32) right_prefix) return -1; - else if (LOAD_U32(left->ids[4]) > (u32) right_prefix) + else if (left->ids[4] > (u32) right_prefix) return 1; /* the right prefix is already checked (+1) */ @@ -700,8 +645,8 @@ snmp_oid_compare(const struct oid *left, const struct oid *right) (int) right_subids); for (int i = 0; i < limit; i++) { - u32 left_id = LOAD_U32(left->ids[i + ARRAY_SIZE(snmp_internet) + 1]); - u32 right_id = LOAD_U32(right->ids[i]); + u32 left_id = left->ids[i + ARRAY_SIZE(snmp_internet + 1)]; + u32 right_id = right->ids[i]; if (left_id < right_id) return -1; else if (left_id > right_id) @@ -723,8 +668,8 @@ snmp_oid_compare(const struct oid *left, const struct oid *right) test_ids: for (int i = 0; i < MIN(left->n_subid, right->n_subid); i++) { - u32 left_id = LOAD_U32(left->ids[i]); - u32 right_id = LOAD_U32(right->ids[i]); + u32 left_id = left->ids[i]; + u32 right_id = right->ids[i]; if (left_id < right_id) return -1; else if (left_id > right_id) @@ -857,6 +802,7 @@ snmp_varbind_ip4(struct snmp_pdu *c, ip4_addr addr) c->buffer = snmp_put_ip4(snmp_varbind_data(c->sr_vb_start), addr); } +#if 0 inline byte * snmp_varbind_nstr2(struct snmp_pdu *c, uint size, const char *str, uint len) { @@ -866,6 +812,7 @@ snmp_varbind_nstr2(struct snmp_pdu *c, uint size, const char *str, uint len) snmp_set_varbind_type(c->sr_vb_start, AGENTX_OCTET_STRING); return snmp_put_nstr(snmp_varbind_data(c->sr_vb_start), str, len); } +#endif /* * snmp_varbind_nstr - fill varbind context with octet string @@ -885,6 +832,19 @@ snmp_varbind_nstr(struct snmp_pdu *c, const char *str, uint len) c->buffer = snmp_put_nstr(snmp_varbind_data(c->sr_vb_start), str, len); } +/* + * snmp_varbind_oid - fill VarBind data with OID @oid_val + * @oid_val - Object Identifier in cpu native byte order + * + * Function puts the @oid_val to the packet byte order. + */ +void +snmp_varbind_oid(struct snmp_pdu *c, const struct oid *oid_val) +{ + snmp_set_varbind_type(c->sr_vb_start, AGENTX_OBJECT_IDENTIFIER); + snmp_oid_to_buf(snmp_varbind_data(c->sr_vb_start), oid_val); +} + inline enum agentx_type snmp_search_res_to_type(enum snmp_search_res r) { @@ -983,65 +943,65 @@ snmp_oid_common_ancestor(const struct oid *left, const struct oid *right, struct { ASSERT(left && right && out); - STORE_U8(out->include, 0); - STORE_U8(out->reserved, 0); - STORE_U8(out->prefix, 0); + out->include, 0; + out->reserved = 0; + out->prefix = 0; u32 offset = 0; - u8 left_ids = LOAD_U8(left->n_subid), right_ids = LOAD_U8(right->n_subid); + u8 left_ids = left->n_subid, right_ids = right->n_subid; int l = snmp_oid_is_prefixed(left), r = snmp_oid_is_prefixed(right); if (l && r) { - if (LOAD_U8(left->prefix) != LOAD_U8(right->prefix)) + if (left->prefix != right->prefix) { - STORE_U8(out->n_subid, 4); + out->n_subid = 4; for (uint id = 0; id < ARRAY_SIZE(snmp_internet); id++) - STORE_U32(out->ids[id], snmp_internet[id]); + out->ids[id] = snmp_internet[id]; return; } - STORE_U8(out->prefix, LOAD_U8(left->prefix)); + out->prefix = left->prefix; } else if (!l && r) { if (left_ids == 0) { /* finish creating NULL OID */ - STORE_U8(out->n_subid, 0); + out->n_subid = 0; return; } for (uint id = 0; id < MIN(ARRAY_SIZE(snmp_internet), left_ids); id++) { - if (LOAD_U32(left->ids[id]) != snmp_internet[id]) + if (left->ids[id] != snmp_internet[id]) { - STORE_U8(out->n_subid, id); + out->n_subid = id; return; } - STORE_U32(out->ids[id], snmp_internet[id]); + out->ids[id] = snmp_internet[id]; } if (left_ids <= ARRAY_SIZE(snmp_internet)) { - STORE_U8(out->n_subid, left_ids); + out->n_subid = left_ids; return; } /* index 4 is conresponding to the prefix in prefixed OID */ - if (LOAD_U32(left->ids[4]) != (u32) LOAD_U8(right->prefix)) + if (left->ids[4] != (u32) right->prefix) { - STORE_U8(out->n_subid, ARRAY_SIZE(snmp_internet)); + out->n_subid = ARRAY_SIZE(snmp_internet); return; } /* delete snmp_internet from out->ids and store OID prefix */ offset = ARRAY_SIZE(snmp_internet) + 1; - STORE_U8(out->n_subid, LOAD_U8(out->n_subid) - ARRAY_SIZE(snmp_internet)); - STORE_U8(out->prefix, LOAD_U8(right->prefix)); + out->n_subid = out->n_subid - ARRAY_SIZE(snmp_internet); + out->prefix = right->prefix; } else if (l && !r) { @@ -1057,12 +1017,12 @@ snmp_oid_common_ancestor(const struct oid *left, const struct oid *right, struct if (left->ids[offset + id] == right->ids[id]) { subids++; - STORE_U32(out->ids[id], LOAD_U32(right->ids[id])); + out->ids[id] = right->ids[id]; } else break; } - STORE_U8(out->n_subid, subids); + out->n_subid = subids; } /* @@ -1115,15 +1075,15 @@ snmp_walk_next(struct mib_tree *tree, struct mib_walk_state *walk, struct snmp_p found = !leaf->call_next(walk, c); } - else if (mib_node_is_leaf(node) && LOAD_U8(c->sr_vb_start->name.include)) + else if (mib_node_is_leaf(node) && c->sr_vb_start->name.include) { found = 1; - STORE_U8(c->sr_vb_start->name.include, 0); + c->sr_vb_start->name.include = 0; } const struct oid *oid = &c->sr_vb_start->name; - u32 skip = (walk->id_pos < LOAD_U8(oid->n_subid)) ? - LOAD_U32(oid->ids[walk->id_pos]) : 0; + u32 skip = (walk->id_pos < oid->n_subid) ? + oid->ids[walk->id_pos] : 0; while (!found && (leaf = mib_tree_walk_next_leaf(tree, walk, skip)) != NULL) { /* mib_tree_walk_next() forces VarBind's name OID overwriting */ @@ -1141,8 +1101,8 @@ snmp_walk_next(struct mib_tree *tree, struct mib_walk_state *walk, struct snmp_p found = 1; oid = &c->sr_vb_start->name; - skip = (walk->id_pos < LOAD_U8(oid->n_subid)) ? - LOAD_U32(oid->ids[walk->id_pos]) : 0; + skip = (walk->id_pos < oid->n_subid) ? + oid->ids[walk->id_pos] : 0; } if (!found) @@ -1186,10 +1146,9 @@ snmp_walk_fill(struct mib_leaf *leaf, struct mib_walk_state *walk, struct snmp_p if (res != SNMP_SEARCH_OK) snmp_set_varbind_type(vb, snmp_search_res_to_type(res)); - u16 type = snmp_load_varbind_type(vb); + u16 type = vb->type; ASSUME(type == leaf->type || type == AGENTX_END_OF_MIB_VIEW || type == AGENTX_NO_SUCH_OBJECT || type == AGENTX_NO_SUCH_INSTANCE); return res; } - diff --git a/proto/snmp/snmp_utils.h b/proto/snmp/snmp_utils.h index 66fa1d37..4ac86aa2 100644 --- a/proto/snmp/snmp_utils.h +++ b/proto/snmp/snmp_utils.h @@ -16,7 +16,6 @@ uint snmp_pkt_len(const byte *start, const byte *end); * AgentX - Variable Binding (VarBind) type utils */ enum snmp_search_res snmp_set_varbind_type(struct agentx_varbind *vb, enum agentx_type t); -enum agentx_type snmp_get_varbind_type(const struct agentx_varbind *vb); int agentx_type_size(enum agentx_type t); /* type Octet String */ @@ -32,6 +31,8 @@ void snmp_oid_copy(struct oid *dest, const struct oid *src); void snmp_oid_copy2(struct oid *dest, const struct oid *src); int snmp_oid_compare(const struct oid *first, const struct oid *second); void snmp_oid_common_ancestor(const struct oid *left, const struct oid *right, struct oid *result); +void snmp_oid_from_buf(struct oid *dest, const struct oid *src); +void snmp_oid_to_buf(struct oid *dest, const struct oid *src); static inline int snmp_oid_is_prefixed(const struct oid *oid) @@ -47,8 +48,7 @@ void snmp_oid_ip4_index(struct oid *o, uint start, ip4_addr addr); /* * AgentX - Variable Binding (VarBind) manupulation */ -uint snmp_varbind_hdr_size_from_oid(const struct oid *oid); -uint snmp_varbind_header_size(const struct agentx_varbind *vb); +uint snmp_varbind_header_size(const struct oid *vb_name); uint snmp_varbind_size(const struct agentx_varbind *vb, uint limit); uint snmp_varbind_size_unsafe(const struct agentx_varbind *vb); size_t snmp_varbind_size_from_len(uint n_subid, enum agentx_type t, uint len); @@ -81,6 +81,7 @@ void snmp_varbind_gauge32(struct snmp_pdu *c, s64 time); void snmp_varbind_ticks(struct snmp_pdu *c, u32 val); void snmp_varbind_ip4(struct snmp_pdu *c, ip4_addr addr); void snmp_varbind_nstr(struct snmp_pdu *c, const char *str, uint len); +void snmp_varbind_oid(struct snmp_pdu *c, const struct oid *oid_val); /* Raw */ byte *snmp_no_such_object(byte *buf, struct agentx_varbind *vb, struct oid *oid); @@ -88,7 +89,6 @@ byte *snmp_no_such_instance(byte *buf, struct agentx_varbind *vb, struct oid *oi byte *snmp_put_str(byte *buf, const char *str); byte *snmp_put_nstr(byte *buf, const char *str, uint len); byte *snmp_put_blank(byte *buf); -byte *snmp_put_oid(byte *buf, struct oid *oid); byte *snmp_put_ip4(byte *buf, ip4_addr ip4); byte *snmp_put_fbyte(byte *buf, u8 data); diff --git a/proto/snmp/subagent.c b/proto/snmp/subagent.c index af768a9d..56f5420a 100644 --- a/proto/snmp/subagent.c +++ b/proto/snmp/subagent.c @@ -77,7 +77,7 @@ snmp_blank_header(struct agentx_header *h, enum agentx_pdu_types type) * snmp_register_ack - handle registration response * @p: SNMP protocol instance * @res: header of agentx-Response-PDU - * @oid: MIB subtree Object Identifier + * @oid: MIB subtree Object Identifier in cpu native byte order */ void snmp_register_ack(struct snmp_proto *p, struct agentx_response *res, const struct oid *oid) @@ -93,9 +93,9 @@ snmp_register_ack(struct snmp_proto *p, struct agentx_response *res, const struc p->registrations_to_ack--; if (res->error == AGENTX_RES_NO_ERROR) - reg->reg_hook_ok(p, (const struct agentx_response *) res, reg); + reg->reg_hook_ok(p, res, reg); else - reg->reg_hook_fail(p, (const struct agentx_response *) res, reg); + reg->reg_hook_fail(p, res, reg); mb_free(reg->oid); mb_free(reg); @@ -172,7 +172,8 @@ open_pdu(struct snmp_proto *p, struct oid *oid) else /* p->timeout > 255 TO_US */ c.buffer = snmp_put_fbyte(c.buffer, (u8) 255); - c.buffer = snmp_put_oid(c.buffer, oid); + snmp_oid_to_buf((struct oid *) c.buffer, oid); + c.buffer += snmp_oid_size(oid); c.buffer = snmp_put_str(c.buffer, cf->description); s = update_packet_size(h, c.buffer); @@ -184,12 +185,12 @@ open_pdu(struct snmp_proto *p, struct oid *oid) * send_notify_pdu - send an agentx-Notify-PDU * @p: SNMP protocol instance * @oid: PDU notification Varbind name (OID) - * @data: PDU Varbind payload - * @size: PDU Varbind payload size - * @include_uptime: flag enabling inclusion of sysUpTime.0 OID + * @data: PDU VarBind payload in packet byte order + * @size: PDU VarBind payload size + * @include_up_time: flag enabling inclusion of sysUpTime.0 OID */ void -snmp_notify_pdu(struct snmp_proto *p, struct oid *oid, void *data, uint size, int include_uptime) +snmp_notify_pdu(struct snmp_proto *p, struct oid *oid, void *data, uint size, int include_up_time) { if (!snmp_is_active(p)) return; @@ -205,7 +206,7 @@ snmp_notify_pdu(struct snmp_proto *p, struct oid *oid, void *data, uint size, in uint sz = AGENTX_HEADER_SIZE + TRAP0_HEADER_SIZE + snmp_oid_size(oid) \ + size; - if (include_uptime) + if (include_up_time) sz += UPTIME_SIZE; /* Make sure that we have enough space in TX buffer */ @@ -217,7 +218,7 @@ snmp_notify_pdu(struct snmp_proto *p, struct oid *oid, void *data, uint size, in p->packet_id++; /* New packet id */ snmp_session(p, h); - if (include_uptime) + if (include_up_time) { /* sysUpTime.0 oid */ STATIC_OID(4) sys_up_time_0 = { @@ -227,17 +228,19 @@ snmp_notify_pdu(struct snmp_proto *p, struct oid *oid, void *data, uint size, in .reserved = 0, .ids = { SNMP_MIB_2, SNMP_SYSTEM, SNMP_SYS_UP_TIME, 0 }, }; - struct oid *uptime_0 = (struct oid *) &sys_up_time_0; + struct oid *up_time_0 = (struct oid *) &sys_up_time_0; - struct agentx_varbind *vb = snmp_create_varbind(c.buffer, uptime_0); - for (uint i = 0; i < uptime_0->n_subid; i++) - STORE_U32(vb->name.ids[i], uptime_0->ids[i]); + struct agentx_varbind *vb = (struct agentx_varbind *) c.buffer; + snmp_oid_to_buf(&vb->name, up_time_0); /* TODO use time from last reconfiguration instead? [config->load_time] */ btime uptime = current_time() - boot_time; snmp_varbind_ticks(&c, (uptime TO_S) / 100); - ASSUME(snmp_test_varbind(vb)); ADVANCE(c.buffer, c.size, snmp_varbind_size_unsafe(vb)); + STORE_U16(vb->type, vb->type); + /* We do not need to call the snmp_varbind_leave() because we used + * the packet byte order in the first place. + */ } /* snmpTrapOID.0 oid */ @@ -250,12 +253,15 @@ snmp_notify_pdu(struct snmp_proto *p, struct oid *oid, void *data, uint size, in }; struct oid *trap_0 = (struct oid *) &snmp_trap_oid_0; - struct agentx_varbind *trap_vb = snmp_create_varbind(c.buffer, trap_0); - for (uint i = 0; i < trap_0->n_subid; i++) - STORE_U32(trap_vb->name.ids[i], trap_0->ids[i]); - trap_vb->type = AGENTX_OBJECT_ID; - snmp_put_oid(snmp_varbind_data(trap_vb), oid); + struct agentx_varbind *trap_vb = (struct agentx_varbind *) c.buffer; + snmp_oid_to_buf(&trap_vb->name, trap_0); + /* snmp_oid_size() works for both byte orders same */ + snmp_varbind_oid(trap_vb, oid); ADVANCE(c.buffer, c.size, snmp_varbind_size_unsafe(trap_vb)); + STORE_U16(trap_vb, trap_vb); + /* We do not need to call the snmp_varbind_leave() because we used the packet + * byte order in the first place. + */ memcpy(c.buffer, data, size); ADVANCE(c.buffer, c.size, size); @@ -298,7 +304,6 @@ un_register_pdu(struct snmp_proto *p, struct oid *oid, u32 bound, uint index, en snmp_pdu_context(&c, p, sk); #define BOUND_SIZE sizeof(u32) - /* conditional +4 for upper-bound (optinal field) */ uint sz = AGENTX_HEADER_SIZE + snmp_oid_size(oid) + ((bound > 1) ? BOUND_SIZE : 0); @@ -321,7 +326,7 @@ un_register_pdu(struct snmp_proto *p, struct oid *oid, u32 bound, uint index, en STORE_U8(ur->reserved, 0); ADVANCE(c.buffer, c.size, sizeof(struct agentx_un_register_hdr)); - (void) snmp_put_oid(c.buffer, oid); + snmp_oid_to_buf((struct oid *) c.buffer, oid); ADVANCE(c.buffer, c.size, snmp_oid_size(oid)); /* place upper-bound if needed */ @@ -389,8 +394,8 @@ close_pdu(struct snmp_proto *p, enum agentx_close_reasons reason) p->packet_id++; snmp_session(p, h); - snmp_put_fbyte(c.buffer, (u8) reason); - ADVANCE(c.buffer, c.size, 4); + (void) snmp_put_fbyte(c.buffer, (u8) reason); + ADVANCE(c.buffer, c.size, REASON_SIZE); uint s = update_packet_size(h, c.buffer); sk_send(sk, s); @@ -466,6 +471,7 @@ parse_test_set_pdu(struct snmp_proto *p, byte * const pkt_start) uint s; /* final packat size */ struct agentx_response *res; /* pointer to reponse in TX buffer */ + /* Presence of full header is guaranteed by parse_pkt() caller */ struct agentx_header *h = (void *) pkt; pkt += AGENTX_HEADER_SIZE; @@ -492,11 +498,13 @@ parse_test_set_pdu(struct snmp_proto *p, byte * const pkt_start) } else if (all_possible) { + /* All values in the agentx-TestSet-PDU are OK, realy to commit them */ response_err_ind(p, res, AGENTX_RES_NO_ERROR, 0); } else { - TRACE(D_PACKETS, "SNMP SET action failed (not writable)"); + // Currently the only reachable branch + //TRACE(D_PACKETS, "SNMP SET action failed (not writable)"); /* This is a recoverable error, we do not need to reset the connection */ response_err_ind(p, res, AGENTX_RES_NOT_WRITABLE, c.index + 1); } @@ -517,6 +525,7 @@ static uint parse_sets_pdu(struct snmp_proto *p, byte * const pkt_start, enum agentx_response_errs err) { byte *pkt = pkt_start; + /* Presence of full header is guaranteed by parse_pkt() caller */ struct agentx_header *h = (void *) pkt; pkt += AGENTX_HEADER_SIZE; uint pkt_size = LOAD_U32(h->payload); @@ -525,8 +534,8 @@ parse_sets_pdu(struct snmp_proto *p, byte * const pkt_start, enum agentx_respons { TRACE(D_PACKETS, "SNMP received malformed set PDU (size)"); snmp_simple_response(p, AGENTX_RES_PARSE_ERROR, 0); - // TODO best solution for possibly malicious pkt_size - return AGENTX_HEADER_SIZE; + snmp_reset(p); + return 0; } struct snmp_pdu c; @@ -546,7 +555,10 @@ parse_sets_pdu(struct snmp_proto *p, byte * const pkt_start, enum agentx_respons /* Reset the connection on unrecoverable error */ if (c.error != AGENTX_RES_NO_ERROR && c.error != err) + { snmp_reset(p); /* error */ + return 0; + } return pkt - pkt_start; } @@ -593,11 +605,6 @@ parse_undo_set_pdu(struct snmp_proto *p, byte *pkt) static uint parse_cleanup_set_pdu(struct snmp_proto *p, byte * const pkt_start) { - TRACE(D_PACKETS, "SNMP received agentx-CleanupSet-PDU"); - (void)p; - // TODO don't forget to free resources allocated by parse_test_set_pdu() - //mb_free(p->tr); - byte *pkt = pkt_start; struct agentx_header *h = (void *) pkt; uint pkt_size = LOAD_U32(h->payload); @@ -605,11 +612,16 @@ parse_cleanup_set_pdu(struct snmp_proto *p, byte * const pkt_start) /* errors are dropped silently, we must not send any agentx-Response-PDU */ if (pkt_size != 0) { - // TODO should we free even for malformed packets ?? - // TODO -> check that data is not freed return AGENTX_HEADER_SIZE; + TRACE(D_PACKET, "SNMP received malformed agentx-CleanupSet-PDU"); + snmp_reset(p); + return 0; } + TRACE(D_PACKETS, "SNMP received agentx-CleanupSet-PDU"); + (void)p; + // TODO don't forget to free resources allocated by parse_test_set_pdu() + //mb_free(p->tr); /* No agentx-Response-PDU is sent in response to agentx-CleanupSet-PDU */ return pkt_size; } @@ -734,7 +746,7 @@ parse_pkt(struct snmp_proto *p, byte *pkt, uint size) default: /* We reset the connection for malformed packet (Unknown packet type) */ - TRACE(D_PACKETS, "SNMP received unknown packet with type %u", LOAD_U8(h->type)); + TRACE(D_PACKETS, "SNMP received unknown packet type (%u)", LOAD_U8(h->type)); snmp_reset(p); return 0; } @@ -770,7 +782,10 @@ parse_response(struct snmp_proto *p, byte *res) // TODO more direct path to mib-specific code TRACE(D_PACKETS, "SNMP received agentx-Response-PDU with error %u", r->error); byte *pkt = res + sizeof(struct agentx_response); - struct oid *failed = (struct oid *) pkt; + const struct oid *failed_buf = (struct oid *) pkt; + uint failed_size = snmp_oid_size(failed_buf); + struct oid *failed = tmp_alloc(failed_size); + snmp_oid_from_buf(failed, failed_buf); snmp_register_ack(p, r, failed); break; @@ -841,7 +856,10 @@ do_response(struct snmp_proto *p, byte *pkt) case SNMP_REGISTER:; pkt += AGENTX_HEADER_SIZE; - const struct oid *oid = (struct oid *) pkt; + const struct oid *oid_buf = (struct oid *) pkt; + uint oid_size = snmp_oid_size(oid_buf); + struct oid *oid = tmp_alloc(oid_size); + snmp_oid_from_buf(oid, oid_buf); snmp_register_ack(p, r, oid); if (p->registrations_to_ack == 0) @@ -859,33 +877,44 @@ do_response(struct snmp_proto *p, byte *pkt) } } -static inline struct oid * +/* + * snmp_oid_prefixize_unsafe - normalize OID to prefixed form + * @dest: destination for normalized OID in native byte order + * @src: source OID in packet byte order + * + * Note that again, snmp_oid_prefixize_unsafe is intended to copy Object + * Identifier from RX buffer to TX buffer but also optionally swap the byte + * order from packet b.o. to cpu native b.o. This is done to simplify the code + * dealing with OIDs. + */ +static inline void snmp_oid_prefixize_unsafe(struct oid *dest, const struct oid *src) { - u8 subids = LOAD_U8(src->n_subid) - 5; - dest->n_subid = subids; - STORE_U8(dest->prefix, (u8) LOAD_U32(src->ids[ARRAY_SIZE(snmp_internet)])); - STORE_U8(dest->include, (LOAD_U8(src->include)) ? 1 : 0); - STORE_U8(dest->reserved, 0); + dest->n_subid = LOAD_U8(src->n_subid) - 5; + dest->prefix = (u8) LOAD_U32(src->ids[ARRAY_SIZE(snmp_internet)]); + dest->include = (LOAD_U8(src->include)) ? 1 : 0; + dest->reserved = 0; /* The LOAD_U32() and STORE_U32() cancel out */ - memcpy(&dest->ids[0], &src->ids[5], subids * sizeof(u32)); + for (i = 0; i < dest->n_subid; i++) + dest->ids[i] = LOAD_U32(src->ids[i + 5]); return dest; } /* - * snmp_vb_to_tx - create varbind from RX buffer OID + * snmp_vb_to_tx - create VarBind in TX buffer from RX buffer OID * @c: PDU context - * @oid: object identifier located in RX buffer + * @oid: Object Identifier located in RX buffer with packet byte order * - * Create NULL initialized VarBind inside TX buffer (from @c) whose vb->name is - * @oid. The @oid prefixed if possible. The result is stored in @c->sr_vb_start. + * Create a NULL initialized VarBind inside TX buffer (from @c) whose name + * is @oid. Because we want to simplify code dealing with OIDs, the byte order + * of the name is optionally swapped to match cpu native byte order. */ void snmp_vb_to_tx(struct snmp_pdu *c, const struct oid *oid) { - uint vb_hdr_size = snmp_varbind_hdr_size_from_oid(oid); + uint vb_hdr_size = snmp_varbind_header_size(oid); (void) snmp_tbuf_reserve(c, vb_hdr_size); ASSERT(c->size >= vb_hdr_size); @@ -898,32 +927,43 @@ snmp_vb_to_tx(struct snmp_pdu *c, const struct oid *oid) { u8 subids = LOAD_U8(oid->n_subid) - 5; ADVANCE(c->buffer, c->size, snmp_oid_size_from_len(subids)); - (void) snmp_oid_prefixize_unsafe(&vb->name, oid); + snmp_oid_prefixize_unsafe(&vb->name, oid); c->sr_vb_start = vb; return; } ADVANCE(c->buffer, c->size, snmp_oid_size(oid)); - snmp_oid_copy2(&vb->name, oid); + snmp_oid_from_buf(&vb->name, oid); c->sr_vb_start = vb; } /* - * snmp_fix_vb - fix VarBind's name OID byte order - * @vb: VarBind to use + * snmp_varbind_leave - transform VarBind to packet byte order + * @vb: prepared VarBind in cpu native byte order */ void -snmp_fix_vb(struct agentx_varbind *vb) +snmp_varbind_leave(struct agentx_varbind *vb) { - snmp_oid_copy(&vb->name, &vb->name); + STORE_U16(vb->type, vb->type); + + /* Does nothing */ + STORE_U16(vb->reserved, 0); + struct oid *oid = &vb->name; + STORE_U8(oid->n_subid, oid->n_subid); + STORE_U8(oid->prefix, oid->prefix); + STORE_U8(oid->include, oid->include); + STORE_U8(oid->reserved, 0); + + for (u8 i = 0; i < oid->n_subid; i++) + STORE_U32(oid->ids[i], oid->ids[i]); } /* * update_packet_size - set PDU size - * @start - pointer to PDU data start (excluding header size) - * @end - pointer after the last PDU byte + * @start: pointer to PDU data start (excluding header size) + * @end: pointer after the last PDU byte * * Return number of bytes in TX buffer (including header size). */ @@ -952,17 +992,17 @@ response_err_ind(struct snmp_proto *p, struct agentx_response *res, enum agentx_ // TODO deal with auto-incrementing of snmp_pdu context c.ind if (err != AGENTX_RES_NO_ERROR && err != AGENTX_RES_GEN_ERROR) { - TRACE(D_PACKETS, "Last PDU resulted in error %u", err); + //TRACE(D_PACKETS, "Last PDU resulted in error %u", err); STORE_U16(res->index, ind); - TRACE(D_PACKETS, "Storing packet size %u (was %u)", sizeof(struct agentx_response) - AGENTX_HEADER_SIZE, LOAD_U32(res->h.payload)); + /* Reset VarBindList to null */ STORE_U32(res->h.payload, sizeof(struct agentx_response) - AGENTX_HEADER_SIZE); } else if (err == AGENTX_RES_GEN_ERROR) { - TRACE(D_PACKETS, "Last PDU resulted in error %u genErr", err); + //TRACE(D_PACKETS, "Last PDU resulted in error %u genErr", err); STORE_U16(res->index, 0); - TRACE(D_PACKETS, "Storing packet size %u (was %u)", sizeof(struct agentx_response) - AGENTX_HEADER_SIZE, LOAD_U32(res->h.payload)); + /* Reset VarBindList to null */ STORE_U32(res->h.payload, sizeof(struct agentx_response) - AGENTX_HEADER_SIZE); } diff --git a/proto/snmp/subagent.h b/proto/snmp/subagent.h index 3c90da14..a2c0807a 100644 --- a/proto/snmp/subagent.h +++ b/proto/snmp/subagent.h @@ -138,26 +138,6 @@ enum agentx_flags { #define LOAD_PTR(src) get_u32(ptr) #endif -#define LOAD_STR(/* byte * */buf, str, length) ({ \ - length = LOAD_PTR(buf); \ - length > 0 ? (str = buf + 4) : (str = NULL); }) - -#define COPY_STR(proto, buf, str, length) ({ \ - length = LOAD_PTR(buf); \ - str = mb_alloc(proto->pool, length + 1); \ - memcpy(str, buf+4, length); \ - str[length] = '\0'; /* set term. char */ \ - buf += 4 + snmp_str_size_from_len(length); }) - -#define SNMP_PUT_OID(buf, size, oid) \ - ({ \ - struct agentx_varbind *vb = (void *) buf; \ - SNMP_FILL_VARBIND(vb, oid); \ - }) - -#define SNMP_FILL_VARBIND(vb, oid) \ - snmp_oid_copy(&(vb)->name, (oid)), snmp_oid_size((oid)) - struct agentx_header { u8 version; u8 type; @@ -189,25 +169,31 @@ struct oid { u32 ids[sbids]; \ } -#define VALUE_U32_HELPER(x) VALUE_U32(x), #define STATIC_OID_INITIALIZER(sbids, pref, ...) \ { \ - .n_subid = VALUE_U8(sbids), \ - .prefix = VALUE_U8(pref), \ - .include = VALUE_U8(0), \ - .reserved = VALUE_U8(0), \ - .ids = { MACRO_FOREACH(VALUE_U32_HELPER, __VA_ARGS__) }, \ + .n_subid = sbids, \ + .prefix = pref, \ + .include = 0, \ + .reserved = 0, \ + .ids = { __VA_ARGS__ }, \ } /* enforced by MIB tree, see mib_tree.h for more info */ #define OID_MAX_LEN 32 +/* + * AgentX VarBind -- Variable Binding + * During the processing of the VarBind, the fields @type and @name are in cpu + * native byte order. This should be fixed by running snmp_varbind_leave() + * before VarBind control pointer abondonment or before packet transmission. + * The data following the structure should always follow the packet byte order. + */ struct agentx_varbind { u16 type; u16 reserved; /* always zero filled */ /* oid part */ struct oid name; - /* AgentX variable binding data optionaly here */ + /* AgentX variable binding data optionally here */ }; struct agentx_search_range {