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);
{
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
**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;
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);
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;
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;
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);
c->buffer += (new - old);
snmp_oid_copy(oid, peer_oid);
- STORE_U8(oid->include, 1);
+ oid->include = 1;
}
ASSUME(oid->n_subid == 9);
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;
}
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);
}
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)
{
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 */
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;
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;
}
/* 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 *));
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 *));
/* 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;
}
}
/* 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;
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.
}
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;
/* 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
{
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;
}
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)
{
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)
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;
}
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;
}
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);
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;
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;
}
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);
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;
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;
}
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;
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]);
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])
}
}
- 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;
}
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]);
{
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)
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 *
{
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;
}
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);
{
/* 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;
}
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;
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));
}
/*
}
/**
- * 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)
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
}
}
-/* 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;
default:
/* Shouldn't happen */
+ die("getting size of VarBind with unknown type (%u)", type);
return 0;
}
}
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;
}
/*
- * 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 ||
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;
}
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;
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;
/* 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);
}
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
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;
}
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;
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])
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) */
(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)
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)
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)
{
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
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)
{
{
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)
{
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;
}
/*
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 */
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)
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;
}
-
* 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 */
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)
/*
* 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);
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);
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);
* 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)
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);
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);
* 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;
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 */
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 = {
.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 */
};
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);
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);
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 */
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);
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;
}
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);
}
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);
{
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;
/* 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;
}
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);
/* 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;
}
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;
}
// 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;
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)
}
}
-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);
{
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).
*/
// 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);
}
#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;
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 {