mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-12-22 09:41:54 +00:00
fixup! SNMP: tmp -- fix byte order handling
This commit is contained in:
parent
dd8d706e1b
commit
538bbadae2
@ -393,6 +393,9 @@ snmp_cleanup(struct snmp_proto *p)
|
||||
rfree(p->lp);
|
||||
p->bgp_trie = NULL;
|
||||
|
||||
rfree(p->end_oids);
|
||||
p->end_oids = NULL;
|
||||
|
||||
p->state = SNMP_DOWN;
|
||||
}
|
||||
|
||||
@ -539,6 +542,7 @@ snmp_start(struct proto *P)
|
||||
p->lp = lp_new(p->pool);
|
||||
p->mib_tree = mb_alloc(p->pool, sizeof(struct mib_tree));
|
||||
p->bgp_trie = f_new_trie(p->lp, 0);
|
||||
p->end_oids = lp_new(p->pool);
|
||||
|
||||
p->startup_timer = tm_new_init(p->pool, snmp_startup_timeout, p, 0, 0);
|
||||
p->ping_timer = tm_new_init(p->pool, snmp_ping_timeout, p, p->timeout, 0);
|
||||
@ -675,7 +679,6 @@ static int
|
||||
snmp_shutdown(struct proto *P)
|
||||
{
|
||||
struct snmp_proto *p = SKIP_BACK(struct snmp_proto, p, P);
|
||||
return snmp_set_state(p, SNMP_DOWN);
|
||||
return snmp_reset(p);
|
||||
}
|
||||
|
||||
|
@ -98,6 +98,7 @@ struct snmp_proto {
|
||||
struct object_lock *lock;
|
||||
pool *pool; /* a shortcut to the procotol mem. pool */
|
||||
linpool *lp; /* linpool for bgp_trie nodes */
|
||||
linpool *end_oids;
|
||||
|
||||
enum snmp_proto_state state;
|
||||
|
||||
|
@ -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->name);
|
||||
uint hdr_size = snmp_varbind_header_size(&(*vb)->name);
|
||||
(void) snmp_tbuf_reserve(c, hdr_size);
|
||||
|
||||
ASSERT(c->size >= hdr_size);
|
||||
@ -158,8 +158,8 @@ snmp_oid_copy(struct oid *dest, const struct oid *src)
|
||||
|
||||
/*
|
||||
* snmp_oid_from_buf - copy OID from RX buffer to dest in native byte order
|
||||
* @dst: destination to use
|
||||
* @src: OID to be copied from
|
||||
* @dst: destination to use (native byte order)
|
||||
* @src: OID to be copied from (packet byte order)
|
||||
*/
|
||||
void
|
||||
snmp_oid_from_buf(struct oid *dst, const struct oid *src)
|
||||
@ -173,6 +173,23 @@ snmp_oid_from_buf(struct oid *dst, const struct oid *src)
|
||||
dst->ids[i] = LOAD_U32(src->ids[i]);
|
||||
}
|
||||
|
||||
/*
|
||||
* snmp_oid_to_buf - copy OID to TX buffer with packet byte order
|
||||
* @dst: destination to use (packet byte order)
|
||||
* @src: OID to be copied from (native byte order)
|
||||
*/
|
||||
void
|
||||
snmp_oid_to_buf(struct oid *dst, const struct oid *src)
|
||||
{
|
||||
STORE_U8(dst->n_subid, src->n_subid);
|
||||
STORE_U8(dst->prefix, src->prefix);
|
||||
STORE_U8(dst->include, (src->include) ? 1 : 0);
|
||||
STORE_U8(dst->reserved, 0);
|
||||
|
||||
for (uint i = 0; i < src->n_subid; i++)
|
||||
STORE_U32(dst->ids[i], src->ids[i]);
|
||||
}
|
||||
|
||||
/*
|
||||
* snmp_oid_duplicate - duplicate an OID from memory pool
|
||||
* @pool: pool to use
|
||||
@ -242,47 +259,6 @@ snmp_oid_size_from_len(uint n_subid)
|
||||
return sizeof(struct oid) + n_subid * sizeof(u32);
|
||||
}
|
||||
|
||||
/*
|
||||
* snmp_set_varbind_type - set VarBind's type field
|
||||
* @vb: Varbind inside TX buffer
|
||||
* @t: a valid type to be set
|
||||
*
|
||||
* This function assumes valid @t.
|
||||
*/
|
||||
inline enum snmp_search_res
|
||||
snmp_set_varbind_type(struct agentx_varbind *vb, enum agentx_type t)
|
||||
{
|
||||
ASSUME(t != AGENTX_INVALID);
|
||||
STORE_U16(vb->type, t);
|
||||
STORE_U16(vb->reserved, 0);
|
||||
|
||||
switch (t)
|
||||
{
|
||||
case AGENTX_END_OF_MIB_VIEW:
|
||||
return SNMP_SEARCH_END_OF_VIEW;
|
||||
case AGENTX_NO_SUCH_OBJECT:
|
||||
return SNMP_SEARCH_NO_OBJECT;
|
||||
case AGENTX_NO_SUCH_INSTANCE:
|
||||
return SNMP_SEARCH_NO_INSTANCE;
|
||||
|
||||
/* valid varbind types */
|
||||
case AGENTX_INTEGER:
|
||||
case AGENTX_OCTET_STRING:
|
||||
case AGENTX_NULL:
|
||||
case AGENTX_OBJECT_ID:
|
||||
case AGENTX_IP_ADDRESS:
|
||||
case AGENTX_COUNTER_32:
|
||||
case AGENTX_GAUGE_32:
|
||||
case AGENTX_TIME_TICKS:
|
||||
case AGENTX_OPAQUE:
|
||||
case AGENTX_COUNTER_64:
|
||||
return SNMP_SEARCH_OK;
|
||||
|
||||
default:
|
||||
die("invalid varbind type %d", (int) t);
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint
|
||||
snmp_get_octet_size(const struct agentx_octet_str *str)
|
||||
{
|
||||
@ -309,13 +285,10 @@ snmp_varbind_header_size(const struct oid *vb_name)
|
||||
*
|
||||
*/
|
||||
uint
|
||||
snmp_varbind_size_unsafe(const struct agentx_varbind *vb, int is_pkt_bo)
|
||||
snmp_varbind_size_unsafe(const struct agentx_varbind *vb)
|
||||
{
|
||||
ASSUME(snmp_test_varbind(vb));
|
||||
|
||||
enum agentx_type type = (is_pkt_bo) ? LOAD_U16(vb->type) : vb->type;
|
||||
int value_size = agentx_type_size(type);
|
||||
|
||||
ASSUME(snmp_test_varbind_type(vb->type));
|
||||
int value_size = agentx_type_size(vb->type);
|
||||
uint vb_header = snmp_varbind_header_size(&vb->name);
|
||||
|
||||
if (value_size == 0)
|
||||
@ -324,7 +297,7 @@ snmp_varbind_size_unsafe(const struct agentx_varbind *vb, int is_pkt_bo)
|
||||
if (value_size > 0)
|
||||
return vb_header + value_size;
|
||||
|
||||
switch (type)
|
||||
switch (vb->type)
|
||||
{
|
||||
case AGENTX_OBJECT_ID:;
|
||||
struct oid *oid = snmp_varbind_data(vb);
|
||||
@ -338,30 +311,31 @@ snmp_varbind_size_unsafe(const struct agentx_varbind *vb, int is_pkt_bo)
|
||||
|
||||
default:
|
||||
/* Shouldn't happen */
|
||||
die("getting size of VarBind with unknown type (%u)", type);
|
||||
die("getting size of VarBind with unknown type (%u)", vb->type);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* snmp_varbind_size - get size of in-buffer VarBind
|
||||
* @vb: VarBind to measure
|
||||
* @vb: VarBind in cpu native byte order to measure
|
||||
* @limit: upper limit of bytes that can be used
|
||||
*
|
||||
* This functions assumes valid VarBind type.
|
||||
* Return 0 for Varbinds longer than limit, Varbind's size otherwise.
|
||||
*/
|
||||
uint
|
||||
uint UNUSED
|
||||
snmp_varbind_size(const struct agentx_varbind *vb, uint limit)
|
||||
{
|
||||
//ASSUME(snmp_test_varbind(vb));
|
||||
|
||||
if (limit < sizeof(struct agentx_varbind))
|
||||
return 0;
|
||||
|
||||
enum agentx_type type = agentx_type_size(snmp_get_varbind_type(vb));
|
||||
if (!snmp_test_varbind_type(vb->type))
|
||||
return 0;
|
||||
|
||||
enum agentx_type type = vb->type;
|
||||
int s = agentx_type_size(type);
|
||||
uint vb_header = snmp_varbind_header_size(vb);
|
||||
uint vb_header = snmp_varbind_header_size(&vb->name);
|
||||
|
||||
if (limit < vb_header)
|
||||
return 0;
|
||||
@ -374,17 +348,27 @@ snmp_varbind_size(const struct agentx_varbind *vb, uint limit)
|
||||
else if (s > 0)
|
||||
return 0;
|
||||
|
||||
uint sz;
|
||||
switch (type)
|
||||
{
|
||||
case AGENTX_OBJECT_ID:;
|
||||
struct oid *oid = snmp_varbind_data(vb);
|
||||
return vb_header + snmp_oid_size(oid);
|
||||
/* snmp_oid_size works for both native and packet byte order */
|
||||
sz = snmp_oid_size(oid);
|
||||
if (limit < vb_header + sz)
|
||||
return 0;
|
||||
else
|
||||
return vb_header + snmp_oid_size(oid);
|
||||
|
||||
case AGENTX_OCTET_STRING:
|
||||
case AGENTX_IP_ADDRESS:
|
||||
case AGENTX_OPAQUE:;
|
||||
struct agentx_octet_str *os = snmp_varbind_data(vb);
|
||||
return vb_header + snmp_get_octet_size(os);
|
||||
sz = snmp_get_octet_size(os);
|
||||
if (limit < vb_header + sz)
|
||||
return 0;
|
||||
else
|
||||
return vb_header + sz;
|
||||
|
||||
default:
|
||||
/* This should not happen */
|
||||
@ -420,10 +404,10 @@ snmp_varbind_size_from_len(uint n_subid, enum agentx_type type, uint len)
|
||||
|
||||
/*
|
||||
* snmp_test_varbind - test validity of VarBind type
|
||||
* @type: Type of VarBind
|
||||
* @type: Type of VarBind in cpu native byte order
|
||||
*/
|
||||
int
|
||||
snmp_test_varbind(u16 type)
|
||||
snmp_test_varbind_type(u16 type)
|
||||
{
|
||||
if (type == AGENTX_INTEGER ||
|
||||
type == AGENTX_OCTET_STRING ||
|
||||
@ -443,31 +427,6 @@ snmp_test_varbind(u16 type)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* snmp_create_varbind - create a null-typed VarBind in buffer
|
||||
* @buf: buffer to use
|
||||
*/
|
||||
struct agentx_varbind *
|
||||
snmp_create_varbind_null(byte *buf)
|
||||
{
|
||||
struct oid o = { 0 };
|
||||
struct agentx_varbind *vb = snmp_create_varbind(buf, &o);
|
||||
snmp_set_varbind_type(vb, AGENTX_NULL);
|
||||
return vb;
|
||||
}
|
||||
|
||||
/*
|
||||
* snmp_create_varbind - initialize in-buffer non-typed VarBind
|
||||
* @buf: pointer to first unused buffer byte
|
||||
* @oid: OID to use as VarBind name
|
||||
*/
|
||||
struct agentx_varbind *
|
||||
snmp_create_varbind(byte *buf, struct oid *oid)
|
||||
{
|
||||
struct agentx_varbind *vb = (void *) buf;
|
||||
snmp_oid_copy(&vb->name, oid);
|
||||
return vb;
|
||||
}
|
||||
|
||||
/**
|
||||
* snmp_oid_ip4_index - check IPv4 address validity in oid
|
||||
@ -645,7 +604,7 @@ snmp_oid_compare(const struct oid *left, const struct oid *right)
|
||||
(int) right_subids);
|
||||
for (int i = 0; i < limit; i++)
|
||||
{
|
||||
u32 left_id = left->ids[i + ARRAY_SIZE(snmp_internet + 1)];
|
||||
u32 left_id = left->ids[i + ARRAY_SIZE(snmp_internet) + 1];
|
||||
u32 right_id = right->ids[i];
|
||||
if (left_id < right_id)
|
||||
return -1;
|
||||
@ -763,7 +722,7 @@ snmp_varbind_type32(struct agentx_varbind *vb, struct snmp_pdu *c, enum agentx_t
|
||||
{
|
||||
ASSUME(agentx_type_size(type) == 4); /* type as 4B representation */
|
||||
|
||||
snmp_set_varbind_type(vb, type);
|
||||
vb->type = type;
|
||||
u32 *data = snmp_varbind_data(vb);
|
||||
STORE_PTR(data, val);
|
||||
data++;
|
||||
@ -798,7 +757,7 @@ snmp_varbind_gauge32(struct snmp_pdu *c, s64 time)
|
||||
inline void
|
||||
snmp_varbind_ip4(struct snmp_pdu *c, ip4_addr addr)
|
||||
{
|
||||
snmp_set_varbind_type(c->sr_vb_start, AGENTX_IP_ADDRESS);
|
||||
c->sr_vb_start->type = AGENTX_IP_ADDRESS;
|
||||
c->buffer = snmp_put_ip4(snmp_varbind_data(c->sr_vb_start), addr);
|
||||
}
|
||||
|
||||
@ -809,7 +768,7 @@ snmp_varbind_nstr2(struct snmp_pdu *c, uint size, const char *str, uint len)
|
||||
if (size < snmp_str_size_from_len(len))
|
||||
return NULL;
|
||||
|
||||
snmp_set_varbind_type(c->sr_vb_start, AGENTX_OCTET_STRING);
|
||||
c->sr_vb_start = AGENTX_OCTET_STRING;
|
||||
return snmp_put_nstr(snmp_varbind_data(c->sr_vb_start), str, len);
|
||||
}
|
||||
#endif
|
||||
@ -828,7 +787,7 @@ snmp_varbind_nstr2(struct snmp_pdu *c, uint size, const char *str, uint len)
|
||||
void
|
||||
snmp_varbind_nstr(struct snmp_pdu *c, const char *str, uint len)
|
||||
{
|
||||
snmp_set_varbind_type(c->sr_vb_start, AGENTX_OCTET_STRING);
|
||||
c->sr_vb_start->type = AGENTX_OCTET_STRING;
|
||||
c->buffer = snmp_put_nstr(snmp_varbind_data(c->sr_vb_start), str, len);
|
||||
}
|
||||
|
||||
@ -841,7 +800,7 @@ 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)
|
||||
{
|
||||
snmp_set_varbind_type(c->sr_vb_start, AGENTX_OBJECT_IDENTIFIER);
|
||||
c->sr_vb_start->type = AGENTX_OBJECT_ID;
|
||||
snmp_oid_to_buf(snmp_varbind_data(c->sr_vb_start), oid_val);
|
||||
}
|
||||
|
||||
@ -943,7 +902,7 @@ snmp_oid_common_ancestor(const struct oid *left, const struct oid *right, struct
|
||||
{
|
||||
ASSERT(left && right && out);
|
||||
|
||||
out->include, 0;
|
||||
out->include = 0;
|
||||
out->reserved = 0;
|
||||
out->prefix = 0;
|
||||
|
||||
@ -1033,8 +992,6 @@ snmp_walk_init(struct mib_tree *tree, struct mib_walk_state *walk, const struct
|
||||
{
|
||||
mib_tree_walk_init(walk, tree);
|
||||
|
||||
snmp_vb_to_tx(c, oid);
|
||||
|
||||
mib_node_u *node = mib_tree_find(tree, walk, &c->sr_vb_start->name);
|
||||
|
||||
// TODO hide me in mib_tree code
|
||||
@ -1116,21 +1073,30 @@ snmp_walk_fill(struct mib_leaf *leaf, struct mib_walk_state *walk, struct snmp_p
|
||||
{
|
||||
struct agentx_varbind *vb = c->sr_vb_start;
|
||||
|
||||
enum agentx_search_res res;
|
||||
if (snmp_oid_compare(&c->sr_vb_start->name, c->sr_o_end) >= 0)
|
||||
{
|
||||
res = AGENTX_END_OF_MIB_VIEW;
|
||||
vb->type = snmp_search_res_to_type(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
if (!leaf)
|
||||
return SNMP_SEARCH_NO_OBJECT;
|
||||
|
||||
uint size = 0;
|
||||
enum agentx_type type = AGENTX_NULL;
|
||||
if (leaf->size >= 0)
|
||||
{
|
||||
if (leaf->type == AGENTX_OCTET_STRING || leaf->type == AGENTX_OPAQUE ||
|
||||
leaf->type == AGENTX_OBJECT_ID)
|
||||
{
|
||||
snmp_set_varbind_type(vb, leaf->type);
|
||||
type = leaf->type;
|
||||
size = leaf->size;
|
||||
}
|
||||
else if (leaf->type != AGENTX_INVALID)
|
||||
{
|
||||
snmp_set_varbind_type(vb, leaf->type);
|
||||
type = leaf->type;
|
||||
size = agentx_type_size(leaf->type);
|
||||
}
|
||||
else
|
||||
@ -1138,17 +1104,17 @@ snmp_walk_fill(struct mib_leaf *leaf, struct mib_walk_state *walk, struct snmp_p
|
||||
}
|
||||
|
||||
(void) snmp_tbuf_reserve(c, size);
|
||||
vb->type = (u16) type;
|
||||
|
||||
enum snmp_search_res res = leaf->filler(walk, c);
|
||||
res = leaf->filler(walk, c);
|
||||
|
||||
vb = c->sr_vb_start;
|
||||
|
||||
if (res != SNMP_SEARCH_OK)
|
||||
snmp_set_varbind_type(vb, snmp_search_res_to_type(res));
|
||||
vb->type = snmp_search_res_to_type(res);
|
||||
|
||||
u16 type = vb->type;
|
||||
ASSUME(type == leaf->type || type == AGENTX_END_OF_MIB_VIEW || type == AGENTX_NO_SUCH_OBJECT ||
|
||||
type == AGENTX_NO_SUCH_INSTANCE);
|
||||
ASSUME(vb->type == leaf->type || vb->type == AGENTX_END_OF_MIB_VIEW ||
|
||||
vb->type == AGENTX_NO_SUCH_OBJECT || vb->type == AGENTX_NO_SUCH_INSTANCE);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
@ -15,7 +15,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);
|
||||
int agentx_type_size(enum agentx_type t);
|
||||
|
||||
/* type Octet String */
|
||||
@ -52,7 +51,7 @@ 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);
|
||||
int snmp_test_varbind(const struct agentx_varbind *vb);
|
||||
int snmp_test_varbind_type(u16 type);
|
||||
void *snmp_varbind_data(const struct agentx_varbind *vb);
|
||||
struct oid *snmp_varbind_set_name_len(struct snmp_pdu *c, struct agentx_varbind **vb, u8 len);
|
||||
void snmp_varbind_duplicate_hdr(struct snmp_pdu *c, struct agentx_varbind **vb);
|
||||
@ -73,8 +72,6 @@ int snmp_test_close_reason(byte value);
|
||||
*/
|
||||
|
||||
/* Functions filling buffer a typed value */
|
||||
struct agentx_varbind *snmp_create_varbind(byte *buf, struct oid *oid);
|
||||
struct agentx_varbind *snmp_create_varbind_null(byte *buf);
|
||||
void snmp_varbind_int(struct snmp_pdu *c, u32 val);
|
||||
void snmp_varbind_counter32(struct snmp_pdu *c, u32 val);
|
||||
void snmp_varbind_gauge32(struct snmp_pdu *c, s64 time);
|
||||
|
@ -35,7 +35,7 @@ static uint parse_response(struct snmp_proto *p, byte *buf);
|
||||
static void do_response(struct snmp_proto *p, byte *buf);
|
||||
static uint parse_gets_pdu(struct snmp_proto *p, byte *pkt);
|
||||
static struct agentx_response *prepare_response(struct snmp_proto *p, struct snmp_pdu *c);
|
||||
static void response_err_ind(struct snmp_proto *p, struct agentx_response *res, enum agentx_response_errs err, u16 ind);
|
||||
static void response_err_ind(struct agentx_response *res, enum agentx_response_errs err, u16 ind);
|
||||
static uint update_packet_size(struct agentx_header *start, byte *end);
|
||||
|
||||
/* standard SNMP internet prefix (.1.3.6.1) */
|
||||
@ -55,7 +55,7 @@ snmp_header(struct agentx_header *h, enum agentx_pdu_types type, u8 flags)
|
||||
{
|
||||
STORE_U8(h->version, AGENTX_VERSION);
|
||||
STORE_U8(h->type, type);
|
||||
STORE_U8(h->flags, flags | SNMP_ORDER);
|
||||
STORE_U8(h->flags, flags | SNMP_BYTE_ORDER);
|
||||
STORE_U8(h->reserved, 0);
|
||||
STORE_U32(h->payload, 0);
|
||||
}
|
||||
@ -123,7 +123,7 @@ snmp_simple_response(struct snmp_proto *p, enum agentx_response_errs error, u16
|
||||
ASSUME(c.size >= sizeof(struct agentx_response));
|
||||
|
||||
struct agentx_response *res = prepare_response(p, &c);
|
||||
response_err_ind(p, res, error, index);
|
||||
response_err_ind(res, error, index);
|
||||
sk_send(sk, sizeof(struct agentx_response));
|
||||
}
|
||||
|
||||
@ -256,9 +256,10 @@ snmp_notify_pdu(struct snmp_proto *p, struct oid *oid, void *data, uint size, in
|
||||
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);
|
||||
c.sr_vb_start = trap_vb;
|
||||
snmp_varbind_oid(&c, oid);
|
||||
ADVANCE(c.buffer, c.size, snmp_varbind_size_unsafe(trap_vb));
|
||||
STORE_U16(trap_vb, trap_vb);
|
||||
STORE_U16(trap_vb->type, trap_vb->type);
|
||||
/* We do not need to call the snmp_varbind_leave() because we used the packet
|
||||
* byte order in the first place.
|
||||
*/
|
||||
@ -493,20 +494,20 @@ parse_test_set_pdu(struct snmp_proto *p, byte * const pkt_start)
|
||||
|
||||
if (c.error != AGENTX_RES_NO_ERROR)
|
||||
{
|
||||
response_err_ind(p, res, c.error, c.index + 1);
|
||||
response_err_ind(res, c.error, c.index + 1);
|
||||
snmp_reset(p);
|
||||
}
|
||||
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);
|
||||
response_err_ind(res, AGENTX_RES_NO_ERROR, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 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);
|
||||
response_err_ind(res, AGENTX_RES_NOT_WRITABLE, c.index + 1);
|
||||
}
|
||||
|
||||
sk_send(sk, s);
|
||||
@ -550,7 +551,7 @@ parse_sets_pdu(struct snmp_proto *p, byte * const pkt_start, enum agentx_respons
|
||||
c.error = err;
|
||||
|
||||
TRACE(D_PACKETS, "SNMP received set PDU with error %u", c.error);
|
||||
response_err_ind(p, r, c.error, 0);
|
||||
response_err_ind(r, c.error, 0);
|
||||
sk_send(p->sock, AGENTX_HEADER_SIZE);
|
||||
|
||||
/* Reset the connection on unrecoverable error */
|
||||
@ -613,7 +614,7 @@ parse_cleanup_set_pdu(struct snmp_proto *p, byte * const pkt_start)
|
||||
if (pkt_size != 0)
|
||||
{
|
||||
return AGENTX_HEADER_SIZE;
|
||||
TRACE(D_PACKET, "SNMP received malformed agentx-CleanupSet-PDU");
|
||||
TRACE(D_PACKETS, "SNMP received malformed agentx-CleanupSet-PDU");
|
||||
snmp_reset(p);
|
||||
return 0;
|
||||
}
|
||||
@ -657,10 +658,11 @@ parse_pkt(struct snmp_proto *p, byte *pkt, uint size)
|
||||
return 0;
|
||||
|
||||
struct agentx_header *h = (struct agentx_header *) pkt;
|
||||
if (h->flags & AGENTX_NETWORK_BYTE_ORDER)
|
||||
if (h->flags & AGENTX_NETWORK_BYTE_ORDER != SNMP_BYTE_ORDER)
|
||||
{
|
||||
TRACE(D_PACKETS, "SNMP received PDU with unexpected byte order");
|
||||
snmp_simple_response(p, AGENTX_RES_GEN_ERROR, 0);
|
||||
if (h->type != AGENTX_RESPONSE_PDU)
|
||||
snmp_simple_response(p, AGENTX_RES_GEN_ERROR, 0);
|
||||
snmp_reset(p);
|
||||
return 0;
|
||||
}
|
||||
@ -671,7 +673,8 @@ parse_pkt(struct snmp_proto *p, byte *pkt, uint size)
|
||||
if (pkt_size > SNMP_PKT_SIZE_MAX)
|
||||
{
|
||||
TRACE(D_PACKETS, "SNMP received PDU is too long");
|
||||
snmp_simple_response(p, AGENTX_RES_GEN_ERROR, 0);
|
||||
if (h->type != AGENTX_RESPONSE_PDU)
|
||||
snmp_simple_response(p, AGENTX_RES_GEN_ERROR, 0);
|
||||
snmp_reset(p);
|
||||
return 0;
|
||||
}
|
||||
@ -802,7 +805,6 @@ parse_response(struct snmp_proto *p, byte *res)
|
||||
case AGENTX_RES_PROCESSING_ERR:
|
||||
default:
|
||||
TRACE(D_PACKETS, "SNMP agentx-Response-PDU with unexepected error %u", r->error);
|
||||
//snmp_stop(p);
|
||||
snmp_reset(p);
|
||||
break;
|
||||
}
|
||||
@ -896,10 +898,8 @@ snmp_oid_prefixize_unsafe(struct oid *dest, const struct oid *src)
|
||||
dest->reserved = 0;
|
||||
|
||||
/* The LOAD_U32() and STORE_U32() cancel out */
|
||||
for (i = 0; i < dest->n_subid; i++)
|
||||
for (u8 i = 0; i < dest->n_subid; i++)
|
||||
dest->ids[i] = LOAD_U32(src->ids[i + 5]);
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -911,7 +911,7 @@ snmp_oid_prefixize_unsafe(struct oid *dest, const struct oid *src)
|
||||
* 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
|
||||
struct agentx_varbind *
|
||||
snmp_vb_to_tx(struct snmp_pdu *c, const struct oid *oid)
|
||||
{
|
||||
uint vb_hdr_size = snmp_varbind_header_size(oid);
|
||||
@ -921,7 +921,7 @@ snmp_vb_to_tx(struct snmp_pdu *c, const struct oid *oid)
|
||||
struct agentx_varbind *vb = (struct agentx_varbind *) c->buffer;
|
||||
ADVANCE(c->buffer, c->size, sizeof(struct agentx_varbind) - sizeof(struct oid));
|
||||
/* Move the c->buffer so that is points at &vb->name */
|
||||
snmp_set_varbind_type(vb, AGENTX_NULL);
|
||||
vb->type = AGENTX_NULL;
|
||||
|
||||
if (snmp_oid_is_prefixable(oid) && !snmp_oid_is_prefixed(oid))
|
||||
{
|
||||
@ -929,14 +929,13 @@ snmp_vb_to_tx(struct snmp_pdu *c, const struct oid *oid)
|
||||
ADVANCE(c->buffer, c->size, snmp_oid_size_from_len(subids));
|
||||
snmp_oid_prefixize_unsafe(&vb->name, oid);
|
||||
|
||||
c->sr_vb_start = vb;
|
||||
return;
|
||||
return vb;
|
||||
}
|
||||
|
||||
ADVANCE(c->buffer, c->size, snmp_oid_size(oid));
|
||||
snmp_oid_from_buf(&vb->name, oid);
|
||||
|
||||
c->sr_vb_start = vb;
|
||||
return vb;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -977,7 +976,6 @@ update_packet_size(struct agentx_header *start, byte *end)
|
||||
|
||||
/*
|
||||
* response_err_ind - update response error and index
|
||||
* @p: SNMP protocol instance
|
||||
* @res: response PDU header
|
||||
* @err: error status
|
||||
* @ind: index of error, ignored for noAgentXError
|
||||
@ -986,7 +984,7 @@ update_packet_size(struct agentx_header *start, byte *end)
|
||||
* error is not noError, also set the corrent response PDU payload size.
|
||||
*/
|
||||
static inline void
|
||||
response_err_ind(struct snmp_proto *p, struct agentx_response *res, enum agentx_response_errs err, u16 ind)
|
||||
response_err_ind(struct agentx_response *res, enum agentx_response_errs err, u16 ind)
|
||||
{
|
||||
STORE_U16(res->error, (u16) err);
|
||||
// TODO deal with auto-incrementing of snmp_pdu context c.ind
|
||||
@ -1019,27 +1017,27 @@ void
|
||||
snmp_get_pdu(struct snmp_proto *p, struct snmp_pdu *c, const struct oid *o_start, struct mib_walk_state *walk)
|
||||
{
|
||||
struct mib_leaf *leaf;
|
||||
leaf = snmp_walk_init(p->mib_tree, walk, o_start, c);
|
||||
leaf = snmp_walk_init(p->mib_tree, walk, &c->sr_vb_start->name, c);
|
||||
|
||||
enum snmp_search_res res;
|
||||
res = snmp_walk_fill(leaf, walk, c);
|
||||
|
||||
if (res != SNMP_SEARCH_OK)
|
||||
snmp_set_varbind_type(c->sr_vb_start, snmp_search_res_to_type(res));
|
||||
c->sr_vb_start->type = snmp_search_res_to_type(res);
|
||||
}
|
||||
|
||||
/* agentx-GetNext-PDU */
|
||||
int
|
||||
snmp_get_next_pdu(struct snmp_proto *p, struct snmp_pdu *c, const struct oid *o_start, struct mib_walk_state *walk)
|
||||
{
|
||||
(void) snmp_walk_init(p->mib_tree, walk, o_start, c);
|
||||
(void) snmp_walk_init(p->mib_tree, walk, &c->sr_vb_start->name, c);
|
||||
struct mib_leaf *leaf = snmp_walk_next(p->mib_tree, walk, c);
|
||||
|
||||
enum snmp_search_res res;
|
||||
res = snmp_walk_fill(leaf, walk, c);
|
||||
|
||||
if (res != SNMP_SEARCH_OK)
|
||||
snmp_set_varbind_type(c->sr_vb_start, AGENTX_END_OF_MIB_VIEW);
|
||||
c->sr_vb_start->type = AGENTX_END_OF_MIB_VIEW;
|
||||
|
||||
return res == SNMP_SEARCH_OK;
|
||||
}
|
||||
@ -1056,53 +1054,63 @@ snmp_get_bulk_pdu(struct snmp_proto *p, struct snmp_pdu *c, const struct oid *o_
|
||||
bulk->has_any |= snmp_get_next_pdu(p, c, o_start, walk);
|
||||
}
|
||||
|
||||
static inline const struct oid *
|
||||
int
|
||||
snmp_load_oids(byte **pkt_ptr, uint *pkt_sz, struct snmp_pdu *c)
|
||||
{
|
||||
byte *pkt = *pkt_ptr;
|
||||
uint pkt_size = *pkt_sz;
|
||||
|
||||
uint sz;
|
||||
const struct oid *start = (const struct oid *) pkt;
|
||||
|
||||
if ((sz = snmp_oid_size(start)) > pkt_size)
|
||||
/* in packet byte order */
|
||||
const struct oid *start_buf = (const struct oid *) pkt;
|
||||
if ((sz = snmp_oid_size(start_buf)) > pkt_size ||
|
||||
LOAD_U8(start_buf->n_subid) >= OID_MAX_LEN)
|
||||
{
|
||||
c->error = AGENTX_RES_PARSE_ERROR;
|
||||
*pkt_ptr = pkt;
|
||||
*pkt_sz = pkt_size;
|
||||
return NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ADVANCE(pkt, pkt_size, sz);
|
||||
|
||||
const struct oid *end = (const struct oid *) pkt;
|
||||
if ((sz = snmp_oid_size(end)) > pkt_size)
|
||||
/* in packet byte order */
|
||||
const struct oid *end_buf = (const struct oid *) pkt;
|
||||
if ((sz = snmp_oid_size(end_buf)) > pkt_size ||
|
||||
LOAD_U8(end_buf->n_subid) >= OID_MAX_LEN)
|
||||
{
|
||||
c->error = AGENTX_RES_PARSE_ERROR;
|
||||
*pkt_ptr = pkt;
|
||||
*pkt_sz = pkt_size;
|
||||
return NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* in cpu native byte order */
|
||||
struct agentx_varbind *start_vb = snmp_vb_to_tx(c, start_buf);
|
||||
|
||||
/* in cpu native byte order */
|
||||
struct oid *end_oid = tmp_alloc(sz);
|
||||
snmp_oid_from_buf(end_oid, end_buf);
|
||||
|
||||
ADVANCE(pkt, pkt_size, sz);
|
||||
|
||||
// TODO: this does not work
|
||||
if (!snmp_is_oid_empty(end) &&
|
||||
snmp_oid_compare(start, end) > 0)
|
||||
if (!snmp_is_oid_empty(end_oid) &&
|
||||
snmp_oid_compare(&start_vb->name, end_oid) > 0)
|
||||
{
|
||||
c->error = AGENTX_RES_GEN_ERROR;
|
||||
*pkt_ptr = pkt;
|
||||
*pkt_sz = pkt_size;
|
||||
return NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ASSERT(start != NULL);
|
||||
ASSERT(end != NULL);
|
||||
ASSERT(start_vb != NULL);
|
||||
ASSERT(end_oid != NULL);
|
||||
|
||||
c->sr_o_end = end;
|
||||
c->sr_vb_start = start_vb;
|
||||
c->sr_o_end = end_oid;
|
||||
*pkt_ptr = pkt;
|
||||
*pkt_sz = pkt_size;
|
||||
return start;
|
||||
return 1; /* ok */
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1169,13 +1177,12 @@ parse_gets_pdu(struct snmp_proto *p, byte * const pkt_start)
|
||||
{
|
||||
lp_restore(tmp_linpool, &tmps);
|
||||
|
||||
const struct oid *start_rx;
|
||||
if (!(start_rx = snmp_load_oids(&pkt, &pkt_size, &c)))
|
||||
if (!snmp_load_oids(&pkt, &pkt_size, &c))
|
||||
{
|
||||
snmp_simple_response(p, c.error,
|
||||
(c.index > UINT16_MAX) ? UINT16_MAX : c.index);
|
||||
snmp_reset(p);
|
||||
return pkt_size + AGENTX_HEADER_SIZE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (h->type)
|
||||
@ -1196,6 +1203,8 @@ parse_gets_pdu(struct snmp_proto *p, byte * const pkt_start)
|
||||
die("implementation failure");
|
||||
}
|
||||
|
||||
snmp_varbind_leave(c.sr_vb_start);
|
||||
|
||||
c.sr_vb_start = NULL;
|
||||
c.sr_o_end = NULL;
|
||||
|
||||
@ -1213,7 +1222,7 @@ parse_gets_pdu(struct snmp_proto *p, byte * const pkt_start)
|
||||
#endif
|
||||
|
||||
/* We update the error, index pair on the beginning of the packet. */
|
||||
response_err_ind(p, response_header, c.error, c.index + 1);
|
||||
response_err_ind(response_header, c.error, c.index + 1);
|
||||
uint s = update_packet_size(&response_header->h, c.buffer);
|
||||
|
||||
/* We send the message in TX buffer. */
|
||||
|
@ -87,7 +87,7 @@ enum agentx_flags {
|
||||
| AGENTX_NETWORK_BYTE_ORDER)
|
||||
|
||||
// TODO - make me compile time option
|
||||
#define SNMP_NATIVE
|
||||
#define SNMP_NETWORK_BYTE_ORDER
|
||||
|
||||
#if !(defined(SNMP_NATIVE) || defined(SNMP_NETWORK_BYTE_ORDER))
|
||||
# error "SNMP: currently support only native byte order or network byte order."
|
||||
@ -99,9 +99,9 @@ enum agentx_flags {
|
||||
#endif
|
||||
|
||||
#if (defined(SNMP_NATIVE) && defined(CPU_BIG_ENDIAN)) || defined(SNMP_NETWORK_BYTE_ORDER)
|
||||
#define SNMP_ORDER AGENTX_NETWORK_BYTE_ORDER
|
||||
#define SNMP_BYTE_ORDER AGENTX_NETWORK_BYTE_ORDER
|
||||
#else
|
||||
#define SNMP_ORDER 0
|
||||
#define SNMP_BYTE_ORDER 0
|
||||
#endif
|
||||
|
||||
/* We recommend using STORE_U32 over VALUE_U32 when possible */
|
||||
@ -359,7 +359,7 @@ snmp_is_active(const struct snmp_proto *p)
|
||||
p->state == SNMP_CONN;
|
||||
}
|
||||
|
||||
void snmp_vb_to_tx(struct snmp_pdu *c, const struct oid *oid);
|
||||
struct agentx_varbind *snmp_vb_to_tx(struct snmp_pdu *c, const struct oid *oid);
|
||||
u8 snmp_get_mib_class(const struct oid *oid);
|
||||
|
||||
void snmp_register_mibs(struct snmp_proto *p);
|
||||
|
Loading…
Reference in New Issue
Block a user