0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-12-22 09:41:54 +00:00

SNMP: Use compile-time selected byte order

In the AgentX communication the subagent chooses the byte order used. To reduce
code complexity, we decide to use compile-time selected byte order in PDU sent.
Supported options are:
  - SNMP_NATIVE: use native CPU byte order
  - SNMP_NETWORK_BYTE_ORDER: use big endian in PDUs, i.e. network byte order
It is recommended not to used both options at the same time (even it is possible
on big endian platforms).
This commit is contained in:
Vojtech Vilimek 2023-11-15 12:37:10 +01:00
parent 709d0fdd19
commit 53856e49c9
7 changed files with 122 additions and 125 deletions

View File

@ -199,8 +199,7 @@ void
snmp_bgp_reg_ok(struct snmp_proto *p, struct agentx_response *r, struct oid *oid) snmp_bgp_reg_ok(struct snmp_proto *p, struct agentx_response *r, struct oid *oid)
{ {
const struct oid *in_buf = ((void *) r) + sizeof(r); const struct oid *in_buf = ((void *) r) + sizeof(r);
int byte_ord = r->h.flags & AGENTX_NETWORK_BYTE_ORDER; struct oid *dup = snmp_prefixize(p, in_buf);
struct oid *dup = snmp_prefixize(p, in_buf, byte_ord);
ASSUME(snmp_bgp_state(oid) == snmp_bgp_state(dup)); ASSUME(snmp_bgp_state(oid) == snmp_bgp_state(dup));
mb_free(dup); mb_free(dup);
@ -1151,7 +1150,7 @@ bgp_fill_dynamic(struct snmp_proto UNUSED *p, struct agentx_varbind *vb,
static byte * static byte *
bgp_fill_static(struct snmp_proto *p, struct agentx_varbind *vb, byte *pkt, uint size bgp_fill_static(struct snmp_proto *p, struct agentx_varbind *vb, byte *pkt, uint size
UNUSED, uint contid UNUSED, int byte_ord UNUSED, u8 state) UNUSED, uint contid UNUSED, u8 state)
{ {
ASSUME((void *) pkt == (void *) vb); ASSUME((void *) pkt == (void *) vb);
@ -1205,7 +1204,7 @@ snmp_bgp_fill(struct snmp_proto *p, struct agentx_varbind *vb,
byte *pkt; byte *pkt;
if (is_static(state)) if (is_static(state))
{ {
pkt = bgp_fill_static(p, vb, c->buffer, c->size, 0, c->byte_ord, state); pkt = bgp_fill_static(p, vb, c->buffer, c->size, 0, state);
ADVANCE(c->buffer, c->size, pkt - c->buffer); ADVANCE(c->buffer, c->size, pkt - c->buffer);
return; return;
} }

View File

@ -36,8 +36,6 @@ enum BGP4_MIB_PEER_TABLE {
#define SNMP_BGP_NEGOTIATED_VER_VALUE 4 #define SNMP_BGP_NEGOTIATED_VER_VALUE 4
#define SNMP_BGP_NEGOTIATED_VER_NO_VALUE 0 #define SNMP_BGP_NEGOTIATED_VER_NO_VALUE 0
struct oid;
void snmp_bgp_register(struct snmp_proto *p); void snmp_bgp_register(struct snmp_proto *p);
void snmp_bgp_reg_ok(struct snmp_proto *p, struct agentx_response *r, struct oid *oid); void snmp_bgp_reg_ok(struct snmp_proto *p, struct agentx_response *r, struct oid *oid);
void snmp_bgp_reg_failed(struct snmp_proto *p, struct agentx_response *r, struct oid *oid); void snmp_bgp_reg_failed(struct snmp_proto *p, struct agentx_response *r, struct oid *oid);

View File

@ -19,12 +19,6 @@
bt_debug("%s expected: %3u actual: %3u\n", \ bt_debug("%s expected: %3u actual: %3u\n", \
#expected, expected, actual); #expected, expected, actual);
#ifdef CPU_BIG_ENDIAN
#define BYTE_ORD 1
#else
#define BYTE_ORD 0
#endif
#define OID_ALLOCATE(size) mb_alloc(&root_pool, sizeof(struct oid) + (size) * sizeof (u32)) #define OID_ALLOCATE(size) mb_alloc(&root_pool, sizeof(struct oid) + (size) * sizeof (u32))
#define OID_INIT(oid, n_subid_, prefix_, include_, arr_) \ #define OID_INIT(oid, n_subid_, prefix_, include_, arr_) \
@ -39,9 +33,10 @@ test_fill(struct snmp_proto *p)
((struct proto *) p)->pool = &root_pool; ((struct proto *) p)->pool = &root_pool;
} }
static void static void UNUSED
test_oid(struct oid *oid, uint base_size) test_oid(struct oid *oid, uint base_size)
{ {
#if 0
/* tests all states one by one */ /* tests all states one by one */
oid->n_subid = base_size + 2; oid->n_subid = base_size + 2;
@ -150,6 +145,7 @@ test_oid(struct oid *oid, uint base_size)
bt_assert(snmp_bgp_state(oid) == BGP_INTERNAL_IN_UPDATE_ELAPSED_TIME); bt_assert(snmp_bgp_state(oid) == BGP_INTERNAL_IN_UPDATE_ELAPSED_TIME);
bt_debug("testing BGP4-MIB::bgpPeerEntry end\n"); bt_debug("testing BGP4-MIB::bgpPeerEntry end\n");
#endif
} }
static int static int
@ -230,14 +226,14 @@ t_s_prefixize(void)
struct snmp_proto snmp_proto; struct snmp_proto snmp_proto;
test_fill(&snmp_proto); test_fill(&snmp_proto);
//struct oid *result = snmp_prefixize(&snmp_proto, nulled, BYTE_ORD); //struct oid *result = snmp_prefixize(&snmp_proto, nulled);
//bt_assert(NULL == result); //bt_assert(NULL == result);
//result != NULL ? mb_free(result) : NULL; //result != NULL ? mb_free(result) : NULL;
struct oid *result; struct oid *result;
struct oid *blank = mb_allocz(&root_pool, sizeof(struct oid)); struct oid *blank = mb_allocz(&root_pool, sizeof(struct oid));
/* here the byte order should not matter */ /* here the byte order should not matter */
result = snmp_prefixize(&snmp_proto, blank, 1 - BYTE_ORD); result = snmp_prefixize(&snmp_proto, blank);
bt_assert(snmp_is_oid_empty(result) == 1); bt_assert(snmp_is_oid_empty(result) == 1);
mb_free(result); result = NULL; mb_free(result); result = NULL;
@ -252,7 +248,7 @@ t_s_prefixize(void)
u32 prefixed_arr[] = { ~((u32) 0), 0, 256 }; u32 prefixed_arr[] = { ~((u32) 0), 0, 256 };
memcpy(&prefixed->ids, prefixed_arr, sizeof(prefixed_arr)); memcpy(&prefixed->ids, prefixed_arr, sizeof(prefixed_arr));
/* struct oid */result = snmp_prefixize(&snmp_proto, prefixed, BYTE_ORD); /* struct oid */result = snmp_prefixize(&snmp_proto, prefixed);
bt_assert(memcmp(result, prefixed, snmp_oid_size(prefixed)) == 0); bt_assert(memcmp(result, prefixed, snmp_oid_size(prefixed)) == 0);
mb_free(result); result = NULL; mb_free(result); result = NULL;
@ -267,7 +263,7 @@ t_s_prefixize(void)
u32 to_prefix_arr[] = {1, 3, 6, 1, 100, ~((u32) 0), 0, 256 }; u32 to_prefix_arr[] = {1, 3, 6, 1, 100, ~((u32) 0), 0, 256 };
memcpy(to_prefix->ids, to_prefix_arr, sizeof(to_prefix_arr)); memcpy(to_prefix->ids, to_prefix_arr, sizeof(to_prefix_arr));
result = snmp_prefixize(&snmp_proto, to_prefix, BYTE_ORD); result = snmp_prefixize(&snmp_proto, to_prefix);
bt_assert(memcmp(result, prefixed, snmp_oid_size(prefixed)) == 0); bt_assert(memcmp(result, prefixed, snmp_oid_size(prefixed)) == 0);
@ -283,7 +279,7 @@ t_s_prefixize(void)
u32 unpref[] = { 65535, 4 }; u32 unpref[] = { 65535, 4 };
memcpy(&unprefixable->ids, unpref, sizeof(unpref) / sizeof(unpref[0])); memcpy(&unprefixable->ids, unpref, sizeof(unpref) / sizeof(unpref[0]));
result = snmp_prefixize(&snmp_proto, unprefixable, BYTE_ORD); result = snmp_prefixize(&snmp_proto, unprefixable);
bt_assert(result == NULL); bt_assert(result == NULL);
result != NULL ? mb_free(result) : NULL; result != NULL ? mb_free(result) : NULL;
@ -296,7 +292,7 @@ t_s_prefixize(void)
u32 unpref2[] = { 1, 3, 6, 2, 1, 2, 15, 6 }; u32 unpref2[] = { 1, 3, 6, 2, 1, 2, 15, 6 };
memcpy(&unprefixable2->ids, unpref2, sizeof(unpref2) / sizeof(unpref2[0])); memcpy(&unprefixable2->ids, unpref2, sizeof(unpref2) / sizeof(unpref2[0]));
result = snmp_prefixize(&snmp_proto, unprefixable2, BYTE_ORD); result = snmp_prefixize(&snmp_proto, unprefixable2);
bt_assert(result == NULL); bt_assert(result == NULL);
result != NULL ? mb_free(result) : NULL; result != NULL ? mb_free(result) : NULL;
@ -514,7 +510,7 @@ int main(int argc, char **argv)
bt_bird_init(); bt_bird_init();
bt_test_suite(t_s_bgp_state, "Function snmp_bgp_state()"); //bt_test_suite(t_s_bgp_state, "Function snmp_bgp_state()");
bt_test_suite(t_s_is_oid_empty, "Function snmp_is_oid_empty()"); bt_test_suite(t_s_is_oid_empty, "Function snmp_is_oid_empty()");

View File

@ -168,7 +168,7 @@ snmp_varbind_header_size(struct agentx_varbind *vb)
} }
uint uint
snmp_varbind_size(struct agentx_varbind *vb, int byte_ord) snmp_varbind_size(struct agentx_varbind *vb)
{ {
uint hdr_size = snmp_varbind_header_size(vb); uint hdr_size = snmp_varbind_header_size(vb);
int s = agentx_type_size(vb->type); int s = agentx_type_size(vb->type);
@ -185,7 +185,7 @@ snmp_varbind_size(struct agentx_varbind *vb, int byte_ord)
* Load length of octet string * Load length of octet string
* (AGENTX_OCTET_STRING, AGENTX_IP_ADDRESS, AGENTX_OPAQUE) * (AGENTX_OCTET_STRING, AGENTX_IP_ADDRESS, AGENTX_OPAQUE)
*/ */
return hdr_size + snmp_str_size_from_len(LOAD_PTR(data, byte_ord)); return hdr_size + snmp_str_size_from_len(LOAD_PTR(data));
} }
/* test if the varbind has valid type */ /* test if the varbind has valid type */
@ -450,7 +450,7 @@ snmp_register_create(struct snmp_proto *p, u8 mib_class)
r->n.prev = r->n.next = NULL; r->n.prev = r->n.next = NULL;
r->session_id = p->session_id; r->session_id = p->session_id;
/* will be incremented by SNMP_SESSION() macro during packet assembly */ /* will be incremented by snmp_session() macro during packet assembly */
r->transaction_id = p->transaction_id; r->transaction_id = p->transaction_id;
r->packet_id = p->packet_id + 1; r->packet_id = p->packet_id + 1;

View File

@ -13,7 +13,7 @@ uint snmp_oid_size(const struct oid *o);
size_t snmp_oid_sizeof(uint n_subid); size_t snmp_oid_sizeof(uint n_subid);
uint snmp_varbind_hdr_size_from_oid(struct oid *oid); uint snmp_varbind_hdr_size_from_oid(struct oid *oid);
uint snmp_varbind_header_size(struct agentx_varbind *vb); uint snmp_varbind_header_size(struct agentx_varbind *vb);
uint snmp_varbind_size(struct agentx_varbind *vb, int byte_ord); uint snmp_varbind_size(struct agentx_varbind *vb);
int snmp_test_varbind(const struct agentx_varbind *vb); int snmp_test_varbind(const struct agentx_varbind *vb);
void snmp_session(const struct snmp_proto *p, struct agentx_header *h); void snmp_session(const struct snmp_proto *p, struct agentx_header *h);
int snmp_has_context(const struct agentx_header *h); int snmp_has_context(const struct agentx_header *h);
@ -46,7 +46,7 @@ void snmp_oid_ip4_index(struct oid *o, uint start, ip4_addr addr);
void snmp_oid_dump(const struct oid *oid); void snmp_oid_dump(const struct oid *oid);
//struct oid *snmp_prefixize(struct snmp_proto *p, struct oid *o, int byte_ord); //struct oid *snmp_prefixize(struct snmp_proto *p, struct oid *o);
struct snmp_register *snmp_register_create(struct snmp_proto *p, u8 mib_class); struct snmp_register *snmp_register_create(struct snmp_proto *p, u8 mib_class);
int snmp_register_same(struct snmp_register *r, struct agentx_header *h, u8 class); int snmp_register_same(struct snmp_register *r, struct agentx_header *h, u8 class);

View File

@ -103,6 +103,21 @@ static const char * const snmp_pkt_type[] UNUSED = {
[AGENTX_RESPONSE_PDU] = "Response-PDU", [AGENTX_RESPONSE_PDU] = "Response-PDU",
}; };
static inline void
snmp_header(struct agentx_header *h, enum agentx_pdu_types type, u8 flags)
{
STORE_U8(h->version, AGENTX_VERSION);
STORE_U8(h->type, (u8) type);
STORE_U8(h->flags, flags | SNMP_ORDER);
STORE_U8(h->pad, 0);
STORE_U32(h->payload, 0);
}
static inline void
snmp_blank_header(struct agentx_header *h, enum agentx_pdu_types type)
{
snmp_header(h, type, 0);
}
/* /*
* snmp_register_ok - registration of OID was successful * snmp_register_ok - registration of OID was successful
@ -251,8 +266,7 @@ open_pdu(struct snmp_proto *p, struct oid *oid)
struct agentx_header *h = (struct agentx_header *) c.buffer; struct agentx_header *h = (struct agentx_header *) c.buffer;
ADVANCE(c.buffer, c.size, AGENTX_HEADER_SIZE); ADVANCE(c.buffer, c.size, AGENTX_HEADER_SIZE);
SNMP_BLANK_HEADER(h, AGENTX_OPEN_PDU); snmp_blank_header(h, AGENTX_OPEN_PDU);
c.byte_ord = h->flags & AGENTX_NETWORK_BYTE_ORDER;
STORE_U32(h->session_id, 1); STORE_U32(h->session_id, 1);
STORE_U32(h->transaction_id, 1); STORE_U32(h->transaction_id, 1);
@ -300,10 +314,9 @@ snmp_notify_pdu(struct snmp_proto *p, struct oid *oid, void *data, uint size, in
struct agentx_header *h = (struct agentx_header *) c.buffer; struct agentx_header *h = (struct agentx_header *) c.buffer;
ADVANCE(c.buffer, c.size, AGENTX_HEADER_SIZE); ADVANCE(c.buffer, c.size, AGENTX_HEADER_SIZE);
SNMP_BLANK_HEADER(h, AGENTX_NOTIFY_PDU); snmp_blank_header(h, AGENTX_NOTIFY_PDU);
p->packet_id++; p->packet_id++;
SNMP_SESSION(h, p); snmp_session(p, h);
c.byte_ord = h->flags & AGENTX_NETWORK_BYTE_ORDER;
if (include_uptime) if (include_uptime)
{ {
@ -320,7 +333,7 @@ snmp_notify_pdu(struct snmp_proto *p, struct oid *oid, void *data, uint size, in
for (uint i = 0; i < uptime.n_subid; i++) for (uint i = 0; i < uptime.n_subid; i++)
STORE_U32(vb->name.ids[i], uptime_ids[i]); STORE_U32(vb->name.ids[i], uptime_ids[i]);
snmp_varbind_ticks(vb, c.size, (current_time() TO_S) / 100); snmp_varbind_ticks(vb, c.size, (current_time() TO_S) / 100);
ADVANCE(c.buffer, c.size, snmp_varbind_size(vb, c.byte_ord)); ADVANCE(c.buffer, c.size, snmp_varbind_size(vb));
} }
/* snmpTrapOID.0 oid */ /* snmpTrapOID.0 oid */
@ -337,7 +350,7 @@ snmp_notify_pdu(struct snmp_proto *p, struct oid *oid, void *data, uint size, in
STORE_U32(trap_vb->name.ids[i], trap0_ids[i]); STORE_U32(trap_vb->name.ids[i], trap0_ids[i]);
trap_vb->type = AGENTX_OBJECT_ID; trap_vb->type = AGENTX_OBJECT_ID;
snmp_put_oid(snmp_varbind_data(trap_vb), oid); snmp_put_oid(snmp_varbind_data(trap_vb), oid);
ADVANCE(c.buffer, c.size, snmp_varbind_size(trap_vb, c.byte_ord)); ADVANCE(c.buffer, c.size, snmp_varbind_size(trap_vb));
memcpy(c.buffer, data, size); memcpy(c.buffer, data, size);
ADVANCE(c.buffer, c.size, size); ADVANCE(c.buffer, c.size, size);
@ -374,8 +387,8 @@ de_allocate_pdu(struct snmp_proto *p, struct oid *oid, enum agentx_pdu_types typ
{ {
struct agentx_header *h; struct agentx_header *h;
SNMP_CREATE(pkt, struct agentx_header, h); SNMP_CREATE(pkt, struct agentx_header, h);
SNMP_BLANK_HEADER(h, type); snmp_blank_header(h, type);
SNMP_SESSION(h,p); snmp_session(p, h);
struct agentx_varbind *vb = (struct agentx_varbind *) pkt; struct agentx_varbind *vb = (struct agentx_varbind *) pkt;
@ -438,10 +451,9 @@ un_register_pdu(struct snmp_proto *p, struct oid *oid, uint bound, uint index, e
struct agentx_header *h = (struct agentx_header *) c.buffer; struct agentx_header *h = (struct agentx_header *) c.buffer;
ADVANCE(c.buffer, c.size, AGENTX_HEADER_SIZE); ADVANCE(c.buffer, c.size, AGENTX_HEADER_SIZE);
SNMP_HEADER(h, (u8) type, is_instance ? AGENTX_FLAG_INSTANCE_REGISTRATION : 0); snmp_header(h, type, is_instance ? AGENTX_FLAG_INSTANCE_REGISTRATION : 0);
p->packet_id++; p->packet_id++;
SNMP_SESSION(h, p); snmp_session(p, h);
c.byte_ord = h->flags & AGENTX_NETWORK_BYTE_ORDER;
struct agentx_un_register_hdr *ur = (struct agentx_un_register_hdr *) c.buffer; struct agentx_un_register_hdr *ur = (struct agentx_un_register_hdr *) c.buffer;
@ -519,10 +531,9 @@ close_pdu(struct snmp_proto *p, enum agentx_close_reasons reason)
struct agentx_header *h = (struct agentx_header *) c.buffer; struct agentx_header *h = (struct agentx_header *) c.buffer;
ADVANCE(c.buffer, c.size, AGENTX_HEADER_SIZE); ADVANCE(c.buffer, c.size, AGENTX_HEADER_SIZE);
SNMP_BLANK_HEADER(h, AGENTX_CLOSE_PDU); snmp_blank_header(h, AGENTX_CLOSE_PDU);
p->packet_id++; p->packet_id++;
SNMP_SESSION(h, p); snmp_session(p, h);
c.byte_ord = h->flags & AGENTX_NETWORK_BYTE_ORDER;
snmp_put_fbyte(c.buffer, (u8) reason); snmp_put_fbyte(c.buffer, (u8) reason);
ADVANCE(c.buffer, c.size, 4); ADVANCE(c.buffer, c.size, 4);
@ -546,8 +557,7 @@ parse_close_pdu(struct snmp_proto *p, byte * const pkt_start, uint size)
byte *pkt = pkt_start; byte *pkt = pkt_start;
struct agentx_header *h = (void *) pkt; struct agentx_header *h = (void *) pkt;
ADVANCE(pkt, size, AGENTX_HEADER_SIZE); ADVANCE(pkt, size, AGENTX_HEADER_SIZE);
int byte_ord = h->flags & AGENTX_NETWORK_BYTE_ORDER; uint pkt_size = LOAD_U32(h->payload);
uint pkt_size = LOAD_U32(h->payload, byte_ord);
if (pkt_size != 0) if (pkt_size != 0)
{ {
@ -622,8 +632,8 @@ addagentcaps_pdu(struct snmp_proto *p, struct oid *cap, char *descr,
struct agentx_header *h; struct agentx_header *h;
SNMP_CREATE(buf, struct agentx_header, h); SNMP_CREATE(buf, struct agentx_header, h);
SNMP_BLANK_HEADER(h, AGENTX_ADD_AGENT_CAPS_PDU); snmp_blank_header(h, AGENTX_ADD_AGENT_CAPS_PDU);
SNMP_SESSION(h, p); snmp_session(p, h);
ADVANCE(buf, size, AGENTX_HEADER_SIZE); ADVANCE(buf, size, AGENTX_HEADER_SIZE);
uint in_pkt; uint in_pkt;
@ -664,7 +674,7 @@ removeagentcaps_pdu(struct snmp_proto *p, struct oid *cap)
struct agentx_header *h; struct agentx_header *h;
SNMP_CREATE(buf, struct agentx_header, h); SNMP_CREATE(buf, struct agentx_header, h);
SNMP_SESSION(h, p); snmp_session(p, h);
ADVANCE(buf, size, AGENTX_HEADER_SIZE); ADVANCE(buf, size, AGENTX_HEADER_SIZE);
uint in_pkt; uint in_pkt;
@ -691,9 +701,8 @@ removeagentcaps_pdu(struct snmp_proto *p, struct oid *cap)
static inline void static inline void
refresh_ids(struct snmp_proto *p, struct agentx_header *h) refresh_ids(struct snmp_proto *p, struct agentx_header *h)
{ {
int byte_ord = h->flags & AGENTX_NETWORK_BYTE_ORDER; p->transaction_id = LOAD_U32(h->transaction_id);
p->transaction_id = LOAD_U32(h->transaction_id, byte_ord); p->packet_id = LOAD_U32(h->packet_id);
p->packet_id = LOAD_U32(h->packet_id, byte_ord);
} }
/* /*
@ -767,7 +776,7 @@ parse_test_set_pdu(struct snmp_proto *p, byte * const pkt_start, uint size)
ADVANCE(pkt, size, snmp_varbind_size(vb, 0)); ADVANCE(pkt, size, snmp_varbind_size(vb, 0));
// TODO remove the mb_alloc() in prefixize() // TODO remove the mb_alloc() in prefixize()
struct oid *work = snmp_prefixize(p, &vb->name, c.byte_ord); struct oid *work = snmp_prefixize(p, &vb->name);
(void)work; (void)work;
all_possible = snmp_testset(p, vb, tr, work, pkt_size); all_possible = snmp_testset(p, vb, tr, work, pkt_size);
mb_free(work); mb_free(work);
@ -807,7 +816,7 @@ parse_set_pdu(struct snmp_proto *p, byte * const pkt_start, uint size, enum agen
byte *pkt = pkt_start; byte *pkt = pkt_start;
struct agentx_header *h = (void *) pkt; struct agentx_header *h = (void *) pkt;
ADVANCE(pkt, size, AGENTX_HEADER_SIZE); ADVANCE(pkt, size, AGENTX_HEADER_SIZE);
uint pkt_size = LOAD_U32(h->payload, h->flags & AGENTX_NETWORK_BYTE_ORDER); uint pkt_size = LOAD_U32(h->payload);
if (pkt_size != 0) if (pkt_size != 0)
{ {
@ -896,7 +905,7 @@ parse_cleanup_set_pdu(struct snmp_proto *p, byte * const pkt_start, uint size)
byte *pkt = pkt_start; byte *pkt = pkt_start;
struct agentx_header *h = (void *) pkt; struct agentx_header *h = (void *) pkt;
uint pkt_size = LOAD_U32(h->payload, h->flags & AGENTX_NETWORK_BYTE_ORDER); uint pkt_size = LOAD_U32(h->payload);
/* errors are dropped silently, we must not send any agentx-Response-PDU */ /* errors are dropped silently, we must not send any agentx-Response-PDU */
if (pkt_size != 0) if (pkt_size != 0)
@ -925,8 +934,7 @@ parse_pkt(struct snmp_proto *p, byte *pkt, uint size, uint *skip)
return 0; return 0;
struct agentx_header *h = (void *) pkt; struct agentx_header *h = (void *) pkt;
int byte_ord = h->flags & AGENTX_NETWORK_BYTE_ORDER; uint pkt_size = LOAD_U32(h->payload);
uint pkt_size = LOAD_U32(h->payload, byte_ord);
/* We need to see the responses for PDU such as /* We need to see the responses for PDU such as
* agentx-Open-PDU, agentx-Register-PDU, ... * agentx-Open-PDU, agentx-Register-PDU, ...
@ -936,7 +944,7 @@ parse_pkt(struct snmp_proto *p, byte *pkt, uint size, uint *skip)
return parse_response(p, pkt, size); return parse_response(p, pkt, size);
if (p->state != SNMP_CONN || if (p->state != SNMP_CONN ||
p->session_id != LOAD_U32(h->session_id, byte_ord)) p->session_id != LOAD_U32(h->session_id))
{ {
struct agentx_header copy = { struct agentx_header copy = {
.session_id = p->session_id, .session_id = p->session_id,
@ -1014,9 +1022,8 @@ parse_response(struct snmp_proto *p, byte *res, uint size)
struct agentx_response *r = (void *) res; struct agentx_response *r = (void *) res;
struct agentx_header *h = &r->h; struct agentx_header *h = &r->h;
int byte_ord = h->flags & AGENTX_NETWORK_BYTE_ORDER; // todo reject not compiled byte order
uint pkt_size = LOAD_U32(h->payload);
uint pkt_size = LOAD_U32(h->payload, byte_ord);
if (size < pkt_size + AGENTX_HEADER_SIZE) if (size < pkt_size + AGENTX_HEADER_SIZE)
return 0; return 0;
@ -1098,7 +1105,6 @@ do_response(struct snmp_proto *p, byte *buf, uint size)
{ {
struct agentx_response *r = (void *) buf; struct agentx_response *r = (void *) buf;
struct agentx_header *h = &r->h; struct agentx_header *h = &r->h;
int byte_ord = h->flags & AGENTX_NETWORK_BYTE_ORDER;
/* TODO make it asynchronous for better speed */ /* TODO make it asynchronous for better speed */
switch (p->state) switch (p->state)
@ -1110,7 +1116,7 @@ do_response(struct snmp_proto *p, byte *buf, uint size)
case SNMP_OPEN: case SNMP_OPEN:
/* copy session info from received packet */ /* copy session info from received packet */
p->session_id = LOAD_U32(h->session_id, byte_ord); p->session_id = LOAD_U32(h->session_id);
refresh_ids(p, h); refresh_ids(p, h);
/* the state needs to be changed before sending registering PDUs to /* the state needs to be changed before sending registering PDUs to
@ -1365,13 +1371,12 @@ parse_gets2_pdu(struct snmp_proto *p, byte * const pkt_start, uint size, uint *s
struct agentx_header *h = (void *) pkt; struct agentx_header *h = (void *) pkt;
ADVANCE(pkt, size, AGENTX_HEADER_SIZE); ADVANCE(pkt, size, AGENTX_HEADER_SIZE);
uint pkt_size = LOAD_U32(h->payload, h->flags & AGENTX_NETWORK_BYTE_ORDER); uint pkt_size = LOAD_U32(h->payload);
sock *sk = p->sock; sock *sk = p->sock;
struct snmp_pdu c; struct snmp_pdu c;
snmp_pdu_context(&c, sk); snmp_pdu_context(&c, sk);
// TODO better handling of endianness // TODO better handling of endianness
c.byte_ord = 0; /* use little-endian */
/* /*
* Get-Bulk processing stops if all the varbind have type END_OF_MIB_VIEW * Get-Bulk processing stops if all the varbind have type END_OF_MIB_VIEW
@ -1397,8 +1402,8 @@ parse_gets2_pdu(struct snmp_proto *p, byte * const pkt_start, uint size, uint *s
bulk_state = (struct agentx_bulk_state) { bulk_state = (struct agentx_bulk_state) {
.getbulk = { .getbulk = {
.non_repeaters = LOAD_U32(bulk_info->non_repeaters, c.byte_ord), .non_repeaters = LOAD_U32(bulk_info->non_repeaters),
.max_repetitions = LOAD_U32(bulk_info->max_repetitions, c.byte_ord), .max_repetitions = LOAD_U32(bulk_info->max_repetitions),
}, },
/* In contrast to the RFC, we use 0-based indices. */ /* In contrast to the RFC, we use 0-based indices. */
.index = 0, .index = 0,
@ -1476,8 +1481,8 @@ parse_gets2_pdu(struct snmp_proto *p, byte * const pkt_start, uint size, uint *s
// TODO check for oversized OIDs before any allocation (in prefixize()) // TODO check for oversized OIDs before any allocation (in prefixize())
/* We create copy of OIDs outside of rx-buffer and also prefixize them */ /* We create copy of OIDs outside of rx-buffer and also prefixize them */
o_start = snmp_prefixize(p, o_start_b, c.byte_ord); o_start = snmp_prefixize(p, o_start_b);
o_end = snmp_prefixize(p, o_end_b, c.byte_ord); o_end = snmp_prefixize(p, o_end_b);
if (!snmp_is_oid_empty(o_end) && snmp_oid_compare(o_start, o_end) > 0) if (!snmp_is_oid_empty(o_end) && snmp_oid_compare(o_start, o_end) > 0)
{ {
@ -1689,10 +1694,9 @@ snmp_ping(struct snmp_proto *p)
struct agentx_header *h = (struct agentx_header *) c.buffer; struct agentx_header *h = (struct agentx_header *) c.buffer;
ADVANCE(c.buffer, c.size, AGENTX_HEADER_SIZE); ADVANCE(c.buffer, c.size, AGENTX_HEADER_SIZE);
SNMP_BLANK_HEADER(h, AGENTX_PING_PDU); snmp_blank_header(h, AGENTX_PING_PDU);
p->packet_id++; p->packet_id++;
SNMP_SESSION(h, p); snmp_session(p, h);
c.byte_ord = AGENTX_NETWORK_BYTE_ORDER;
/* sending only header -> pkt - buf */ /* sending only header -> pkt - buf */
uint s = update_packet_size(p, sk->tpos, c.buffer); uint s = update_packet_size(p, sk->tpos, c.buffer);
@ -1799,14 +1803,13 @@ search_mib(struct snmp_proto *p, const struct oid *o_start, const struct oid *o_
* snmp_prefixize - return prefixed OID copy if possible * snmp_prefixize - return prefixed OID copy if possible
* @proto: allocation pool holder * @proto: allocation pool holder
* @oid: from packet loaded object identifier * @oid: from packet loaded object identifier
* @byte_ord: byte order of @oid
* *
* Return prefixed (meaning with nonzero prefix field) oid copy of @oid if * Return prefixed (meaning with nonzero prefix field) oid copy of @oid if
* possible, NULL otherwise. Returned pointer is always allocated from @proto's * possible, NULL otherwise. Returned pointer is always allocated from @proto's
* pool not a pointer to RX-buffer (from which is most likely @oid). * pool not a pointer to RX-buffer (from which is most likely @oid).
*/ */
struct oid * struct oid *
snmp_prefixize(struct snmp_proto *proto, const struct oid *oid, int byte_ord) snmp_prefixize(struct snmp_proto *proto, const struct oid *oid)
{ {
ASSERT(oid != NULL); ASSERT(oid != NULL);
@ -1826,7 +1829,7 @@ snmp_prefixize(struct snmp_proto *proto, const struct oid *oid, int byte_ord)
return NULL; return NULL;
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
if (LOAD_U32(oid->ids[i], byte_ord) != snmp_internet[i]) if (LOAD_U32(oid->ids[i]) != snmp_internet[i])
return NULL; return NULL;
/* validity check here */ /* validity check here */
@ -1923,8 +1926,8 @@ prepare_response(struct snmp_proto *p, struct snmp_pdu *c)
struct agentx_response *r = (void *) c->buffer; struct agentx_response *r = (void *) c->buffer;
struct agentx_header *h = &r->h; struct agentx_header *h = &r->h;
SNMP_BLANK_HEADER(h, AGENTX_RESPONSE_PDU); snmp_blank_header(h, AGENTX_RESPONSE_PDU);
SNMP_SESSION(h, p); snmp_session(p, h);
/* protocol doesn't care about subagent upTime */ /* protocol doesn't care about subagent upTime */
STORE_U32(r->uptime, 0); STORE_U32(r->uptime, 0);

View File

@ -69,66 +69,83 @@ enum snmp_search_res {
#define SNMP_REGISTER_TREE 0 #define SNMP_REGISTER_TREE 0
#define SNMP_REGISTER_INSTANCE 1 #define SNMP_REGISTER_INSTANCE 1
enum agentx_flags {
AGENTX_FLAG_BLANK = 0x00,
AGENTX_FLAG_INSTANCE_REGISTRATION = 0x01,
AGENTX_FLAG_NEW_INDEX = 0x02,
AGENTX_FLAG_ANY_INDEX = 0x04,
AGENTX_NON_DEFAULT_CONTEXT = 0x08,
AGENTX_NETWORK_BYTE_ORDER = 0x10,
} PACKED;
#define AGENTX_FLAGS_MASK (AGENTX_FLAG_INSTANCE_REGISTRATION \
| AGENTX_FLAG_NEW_INDEX \
| AGENTX_FLAG_ANY_INDEX \
| AGENTX_NON_DEFAULT_CONTEXT \
| AGENTX_NETWORK_BYTE_ORDER)
// TODO - make me compile time option
#define SNMP_NATIVE #define SNMP_NATIVE
#if !(defined(SNMP_NATIVE) || defined(SNMP_NETWORK_BYTE_ORDER))
# error "SNMP: currently support only native byte order or network byte order."
#endif
#if defined(SNMP_NATIVE) && defined(SNMP_NETWORK_BYTE_ORDER) && !defined(CPU_BIG_ENDIAN)
# error "SNMP: couldn't use both native byte order and network byte order " \
"(big endian) on little endian machine."
#endif
#if (defined(SNMP_NATIVE) && defined(CPU_BIG_ENDIAN)) || defined(SNMP_NETWORK_BYTE_ORDER)
#define SNMP_ORDER AGENTX_NETWORK_BYTE_ORDER
#else
#define SNMP_ORDER 0
#endif
#ifdef SNMP_NATIVE #ifdef SNMP_NATIVE
#define STORE_U32(dest, val) ((dest) = (u32) (val)) #define STORE_U32(dest, val) ((dest) = (u32) (val))
#define STORE_U16(dest, val) ((dest) = (u16) (val)) #define STORE_U16(dest, val) ((dest) = (u16) (val))
#define STORE_U8(dest, val) ((dest) = (u8) (val)) #define STORE_U8(dest, val) ((dest) = (u8) (val))
#define STORE_PTR(ptr, val) (*((u32 *) (ptr)) = (u32) (val)) #define STORE_PTR(ptr, val) (*((u32 *) (ptr)) = (u32) (val))
#else
#define LOAD_U32(src) *((u32 *) &(src))
#define LOAD_U16(src) *((u16 *) &(src))
#define LOAD_U8(src) *((u8 *) &(src))
#define LOAD_PTR(ptr) *((u32 *) (ptr))
#endif
#if defined(SNMP_NETWORK_BYTE_ORDER) && (!defined(SNMP_NATIVE) || defined(CPU_BIG_ENDIAN))
#define STORE_U32(dest, val) put_u32(&(dest), (val)) #define STORE_U32(dest, val) put_u32(&(dest), (val))
#define STORE_U16(dest, val) put_u16(&(dest), (val)) #define STORE_U16(dest, val) put_u16(&(dest), (val))
#define STORE_U8(dest, val) put_u8(&(dest), (val)) #define STORE_U8(dest, val) put_u8(&(dest), (val))
#define STORE_PTR(ptr, val) put_u32(ptr, val) #define STORE_PTR(ptr, val) put_u32(ptr, val)
#define LOAD_U32(src) get_u32(&(src))
#define LOAD_U16(src) get_u16(&(src))
#define LOAD_U8(src) get_u8(&(src))
#define LOAD_PTR(src) get_u32(ptr)
#endif #endif
/* storing byte (u8) is always the same */ #define LOAD_STR(/* byte * */buf, str, length) ({ \
#define SNMP_HEADER_(h, v, t, f) \ length = LOAD_PTR(buf); \
put_u8(&h->version, v); \
put_u8(&h->type, t); \
put_u8(&h->flags, f); \
put_u8(&h->pad, 0); \
STORE_U32(h->payload, 0)
#ifdef SNMP_NATIVE
#define SNMP_HEADER(h,t,f) SNMP_HEADER_(h, AGENTX_VERSION, t, f)
#else
#define SNMP_HEADER(h,t,f) \
SNMP_HEADER_(h, AGENTX_VERSION, t, f | SNMP_NETWORK_BYTE_ORDER)
#endif
#define SNMP_BLANK_HEADER(h, t) SNMP_HEADER(h, t, AGENTX_FLAG_BLANK)
#define SNMP_SESSION(h, p) \
STORE_U32(h->session_id, p->session_id); \
STORE_U32(h->transaction_id, p->transaction_id); \
STORE_U32(h->packet_id, p->packet_id)
#define LOAD_U32(v, bo) ((bo) ? get_u32(&v) : (u32) (v))
#define LOAD_U16(v, bo) ((bo) ? get_u16(&v) : (u16) (v))
#define LOAD_PTR(v, bo) ((bo) ? get_u32(v) : *((u32 *) v))
#define LOAD_STR(/* byte * */buf, str, length, byte_ord) ({ \
length = LOAD_PTR(buf, byte_ord); \
length > 0 ? (str = buf + 4) : (str = NULL); }) length > 0 ? (str = buf + 4) : (str = NULL); })
#define COPY_STR(proto, buf, str, length, byte_order) ({ \ #define COPY_STR(proto, buf, str, length) ({ \
length = LOAD_PTR(buf, byte_order); \ length = LOAD_PTR(buf); \
/*log(L_INFO "LOAD_STR(), %p %u", proto->pool, length + 1); */ \ /*log(L_INFO "LOAD_STR(), %p %u", proto->pool, length + 1); */ \
str = mb_alloc(proto->pool, length + 1); \ str = mb_alloc(proto->pool, length + 1); \
memcpy(str, buf+4, length); \ memcpy(str, buf+4, length); \
str[length] = '\0'; /* set term. char */ \ str[length] = '\0'; /* set term. char */ \
buf += 4 + snmp_str_size_from_len(length); }) buf += 4 + snmp_str_size_from_len(length); })
#define SNMP_PUT_OID(buf, size, oid, byte_ord) \ #define SNMP_PUT_OID(buf, size, oid) \
({ \ ({ \
struct agentx_varbind *vb = (void *) buf; \ struct agentx_varbind *vb = (void *) buf; \
SNMP_FILL_VARBIND(vb, oid, byte_ord); \ SNMP_FILL_VARBIND(vb, oid); \
}) })
#define SNMP_FILL_VARBIND(vb, oid, byte_ord) \ #define SNMP_FILL_VARBIND(vb, oid) \
snmp_oid_copy(&(vb)->name, (oid), (byte_ord)), snmp_oid_size((oid)) snmp_oid_copy(&(vb)->name, (oid)), snmp_oid_size((oid))
struct agentx_header { struct agentx_header {
u8 version; u8 version;
@ -217,21 +234,6 @@ enum agentx_pdu_types {
AGENTX_RESPONSE_PDU = 18, /* agentx-Response-PDU */ AGENTX_RESPONSE_PDU = 18, /* agentx-Response-PDU */
} PACKED; } PACKED;
enum agentx_flags {
AGENTX_FLAG_BLANK = 0x00,
AGENTX_FLAG_INSTANCE_REGISTRATION = 0x01,
AGENTX_FLAG_NEW_INDEX = 0x02,
AGENTX_FLAG_ANY_INDEX = 0x04,
AGENTX_NON_DEFAULT_CONTEXT = 0x08,
AGENTX_NETWORK_BYTE_ORDER = 0x10,
} PACKED;
#define AGENTX_FLAGS_MASK (AGENTX_FLAG_INSTANCE_REGISTRATION \
| AGENTX_FLAG_NEW_INDEX \
| AGENTX_FLAG_ANY_INDEX \
| AGENTX_NON_DEFAULT_CONTEXT \
| AGENTX_NETWORK_BYTE_ORDER)
/* agentx-Close-PDU close reasons */ /* agentx-Close-PDU close reasons */
enum agentx_close_reasons { enum agentx_close_reasons {
AGENTX_CLOSE_OTHER = 1, AGENTX_CLOSE_OTHER = 1,
@ -281,7 +283,6 @@ enum agentx_response_errs {
struct snmp_pdu { struct snmp_pdu {
byte *buffer; /* pointer to buffer */ byte *buffer; /* pointer to buffer */
uint size; /* unused space in buffer */ uint size; /* unused space in buffer */
int byte_ord; /* flag signaling NETWORK_BYTE_ORDER */
enum agentx_response_errs error; /* storage for result of current action */ enum agentx_response_errs error; /* storage for result of current action */
u32 index; /* index on which the error was found */ u32 index; /* index on which the error was found */
}; };
@ -305,7 +306,7 @@ void snmp_notify_pdu(struct snmp_proto *p, struct oid *oid, void *data, uint siz
void snmp_manage_tbuf(struct snmp_proto *p, struct snmp_pdu *c); void snmp_manage_tbuf(struct snmp_proto *p, struct snmp_pdu *c);
struct oid *snmp_prefixize(struct snmp_proto *p, const struct oid *o, int byte_ord); struct oid *snmp_prefixize(struct snmp_proto *p, const struct oid *o);
u8 snmp_get_mib_class(const struct oid *oid); u8 snmp_get_mib_class(const struct oid *oid);