mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2025-01-03 07:31:54 +00:00
Merge branch 'vv-test' into proto-snmp
This commit is contained in:
commit
3b87af96f3
@ -1302,3 +1302,12 @@ snmp_bgp_fill(struct snmp_proto *p, struct agentx_varbind *vb,
|
|||||||
ADVANCE(c->buffer, c->size, snmp_varbind_header_size(vb));
|
ADVANCE(c->buffer, c->size, snmp_varbind_header_size(vb));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
int
|
||||||
|
snmp_bgp_testset(struct snmp_proto *p, const struct agentx_varbind *vb, void *tr, struct oid *oid, uint pkt_size)
|
||||||
|
{
|
||||||
|
// TODO: check the type of varbind vb and it's value correctness, don't overflow the pkt_size
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
@ -46,6 +46,7 @@ u8 snmp_bgp_getnext_valid(u8 state);
|
|||||||
struct oid *snmp_bgp_search(struct snmp_proto *p, struct oid *o_start, struct oid *o_end, uint contid);
|
struct oid *snmp_bgp_search(struct snmp_proto *p, struct oid *o_start, struct oid *o_end, uint contid);
|
||||||
enum snmp_search_res snmp_bgp_search2(struct snmp_proto *p, struct oid **searched, const struct oid *o_end, uint contid);
|
enum snmp_search_res snmp_bgp_search2(struct snmp_proto *p, struct oid **searched, const struct oid *o_end, uint contid);
|
||||||
void snmp_bgp_fill(struct snmp_proto *p, struct agentx_varbind *vb, struct snmp_pdu *c);
|
void snmp_bgp_fill(struct snmp_proto *p, struct agentx_varbind *vb, struct snmp_pdu *c);
|
||||||
|
//int snmp_bgp_testset(struct snmp_proto *p, const struct agentx_varbind *vb, void* tr, struct oid *oid, uint pkt_type);
|
||||||
|
|
||||||
void snmp_bgp_notify_established(struct snmp_proto *p, struct bgp_proto *bgp);
|
void snmp_bgp_notify_established(struct snmp_proto *p, struct bgp_proto *bgp);
|
||||||
void snmp_bgp_notify_backward_trans(struct snmp_proto *p, struct bgp_proto *bgp);
|
void snmp_bgp_notify_backward_trans(struct snmp_proto *p, struct bgp_proto *bgp);
|
||||||
|
@ -134,8 +134,6 @@ snmp_cleanup(struct snmp_proto *p)
|
|||||||
rfree(p->lock);
|
rfree(p->lock);
|
||||||
p->lock = NULL;
|
p->lock = NULL;
|
||||||
|
|
||||||
p->partial_response = NULL;
|
|
||||||
|
|
||||||
struct snmp_register *r, *r2;
|
struct snmp_register *r, *r2;
|
||||||
WALK_LIST_DELSAFE(r, r2, p->register_queue)
|
WALK_LIST_DELSAFE(r, r2, p->register_queue)
|
||||||
{
|
{
|
||||||
@ -254,13 +252,9 @@ snmp_start_locked(struct object_lock *lock)
|
|||||||
}
|
}
|
||||||
|
|
||||||
snmp_log("opening socket");
|
snmp_log("opening socket");
|
||||||
|
/* Try opening the socket, schedule a retry on fail */
|
||||||
if (sk_open(s) < 0)
|
if (sk_open(s) < 0)
|
||||||
{
|
tm_set(p->startup_timer, current_time() + p->timeout S);
|
||||||
// TODO rather set the startup timer, then reset whole SNMP proto
|
|
||||||
log(L_ERR "Cannot open listening socket");
|
|
||||||
snmp_down(p);
|
|
||||||
// TODO go back to SNMP_INIT and try reconnecting after timeout
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* this function is internal and shouldn't be used outside the snmp module */
|
/* this function is internal and shouldn't be used outside the snmp module */
|
||||||
@ -309,10 +303,7 @@ static void
|
|||||||
snmp_stop_timeout(timer *t)
|
snmp_stop_timeout(timer *t)
|
||||||
{
|
{
|
||||||
snmp_log("stop timer triggered");
|
snmp_log("stop timer triggered");
|
||||||
|
snmp_down(t->data);
|
||||||
struct snmp_proto *p = t->data;
|
|
||||||
|
|
||||||
snmp_down(p);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -338,7 +329,6 @@ snmp_start(struct proto *P)
|
|||||||
|
|
||||||
p->to_send = 0;
|
p->to_send = 0;
|
||||||
p->errs = 0;
|
p->errs = 0;
|
||||||
p->partial_response = NULL;
|
|
||||||
|
|
||||||
p->startup_timer = tm_new_init(p->pool, snmp_startup_timeout, p, 0, 0);
|
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, 0, 0);
|
p->ping_timer = tm_new_init(p->pool, snmp_ping_timeout, p, 0, 0);
|
||||||
@ -366,7 +356,6 @@ snmp_start(struct proto *P)
|
|||||||
HASH_INSERT(p->context_hash, SNMP_H_CONTEXT, defaultc);
|
HASH_INSERT(p->context_hash, SNMP_H_CONTEXT, defaultc);
|
||||||
|
|
||||||
p->context_id_map[0] = defaultc;
|
p->context_id_map[0] = defaultc;
|
||||||
p->bgp_trie = NULL;
|
|
||||||
|
|
||||||
struct snmp_bond *b;
|
struct snmp_bond *b;
|
||||||
WALK_LIST(b, cf->bgp_entries)
|
WALK_LIST(b, cf->bgp_entries)
|
||||||
|
@ -161,12 +161,6 @@ struct snmp_proto {
|
|||||||
|
|
||||||
uint to_send;
|
uint to_send;
|
||||||
uint errs;
|
uint errs;
|
||||||
|
|
||||||
/*
|
|
||||||
* if the packet hasn't been fully recieved, partial_reponse points
|
|
||||||
* into the TX buffer to the Response-PDU header (needed for packet payload)
|
|
||||||
*/
|
|
||||||
struct agentx_response *partial_response;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//void snmp_tx(sock *sk);
|
//void snmp_tx(sock *sk);
|
||||||
|
@ -38,7 +38,7 @@ static struct oid *search_mib(struct snmp_proto *p, const struct oid *o_start, c
|
|||||||
|
|
||||||
u32 snmp_internet[] = { SNMP_ISO, SNMP_ORG, SNMP_DOD, SNMP_INTERNET };
|
u32 snmp_internet[] = { SNMP_ISO, SNMP_ORG, SNMP_DOD, SNMP_INTERNET };
|
||||||
|
|
||||||
static const char * const snmp_errs[] = {
|
static const char * const snmp_errs[] UNUSED = {
|
||||||
#define SNMP_ERR_SHIFT 256
|
#define SNMP_ERR_SHIFT 256
|
||||||
[AGENTX_RES_OPEN_FAILED - SNMP_ERR_SHIFT] = "Open failed",
|
[AGENTX_RES_OPEN_FAILED - SNMP_ERR_SHIFT] = "Open failed",
|
||||||
[AGENTX_RES_NOT_OPEN - SNMP_ERR_SHIFT] = "Not open",
|
[AGENTX_RES_NOT_OPEN - SNMP_ERR_SHIFT] = "Not open",
|
||||||
@ -55,7 +55,7 @@ static const char * const snmp_errs[] = {
|
|||||||
[AGENTX_RES_PROCESSING_ERR - SNMP_ERR_SHIFT] = "Processing error",
|
[AGENTX_RES_PROCESSING_ERR - SNMP_ERR_SHIFT] = "Processing error",
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char * const snmp_pkt_type[] = {
|
static const char * const snmp_pkt_type[] UNUSED = {
|
||||||
[AGENTX_OPEN_PDU] = "Open-PDU",
|
[AGENTX_OPEN_PDU] = "Open-PDU",
|
||||||
[AGENTX_CLOSE_PDU] = "Close-PDU",
|
[AGENTX_CLOSE_PDU] = "Close-PDU",
|
||||||
[AGENTX_REGISTER_PDU] = "Register-PDU",
|
[AGENTX_REGISTER_PDU] = "Register-PDU",
|
||||||
@ -108,13 +108,7 @@ open_pdu(struct snmp_proto *p, struct oid *oid)
|
|||||||
c.buffer = snmp_put_str(c.buffer, cf->description);
|
c.buffer = snmp_put_str(c.buffer, cf->description);
|
||||||
|
|
||||||
uint s = update_packet_size(p, buf, c.buffer);
|
uint s = update_packet_size(p, buf, c.buffer);
|
||||||
int ret = sk_send(sk, s);
|
sk_send(sk, s);
|
||||||
if (ret > 0)
|
|
||||||
snmp_log("sk_send OK!");
|
|
||||||
else if (ret == 0)
|
|
||||||
snmp_log("sk_send sleep");
|
|
||||||
else
|
|
||||||
snmp_log("sk_send error");
|
|
||||||
#undef TIMEOUT_SIZE
|
#undef TIMEOUT_SIZE
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -184,13 +178,7 @@ snmp_notify_pdu(struct snmp_proto *p, struct oid *oid, void *data, uint size, in
|
|||||||
ADVANCE(c.buffer, c.size, size);
|
ADVANCE(c.buffer, c.size, size);
|
||||||
|
|
||||||
uint s = update_packet_size(p, sk->tbuf, c.buffer);
|
uint s = update_packet_size(p, sk->tbuf, c.buffer);
|
||||||
int ret = sk_send(sk, s);
|
sk_send(sk, s);
|
||||||
if (ret > 0)
|
|
||||||
snmp_log("sk_send OK!");
|
|
||||||
else if (ret == 0)
|
|
||||||
snmp_log("sk_send sleep");
|
|
||||||
else
|
|
||||||
snmp_log("sk_send error");
|
|
||||||
|
|
||||||
#undef TRAP0_HEADER_SIZE
|
#undef TRAP0_HEADER_SIZE
|
||||||
#undef UPTIME_SIZE
|
#undef UPTIME_SIZE
|
||||||
@ -208,7 +196,7 @@ de_allocate_pdu(struct snmp_proto *p, struct oid *oid, u8 type)
|
|||||||
|
|
||||||
if (size > AGENTX_HEADER_SIZE + )
|
if (size > AGENTX_HEADER_SIZE + )
|
||||||
{
|
{
|
||||||
snmp_log("de_allocate_pdu()");
|
//snmp_log("de_allocate_pdu()");
|
||||||
|
|
||||||
struct agentx_header *h;
|
struct agentx_header *h;
|
||||||
SNMP_CREATE(pkt, struct agentx_header, h);
|
SNMP_CREATE(pkt, struct agentx_header, h);
|
||||||
@ -221,7 +209,7 @@ de_allocate_pdu(struct snmp_proto *p, struct oid *oid, u8 type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
snmp_log("de_allocate_pdu(): insufficient size");
|
{}//snmp_log("de_allocate_pdu(): insufficient size");
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -289,13 +277,7 @@ un_register_pdu(struct snmp_proto *p, struct oid *oid, uint len, uint index, u8
|
|||||||
uint s = update_packet_size(p, buf, c.buffer);
|
uint s = update_packet_size(p, buf, c.buffer);
|
||||||
|
|
||||||
//snmp_log("sending (un)register %s", snmp_pkt_type[type]);
|
//snmp_log("sending (un)register %s", snmp_pkt_type[type]);
|
||||||
int ret = sk_send(sk, s);
|
sk_send(sk, s);
|
||||||
if (ret > 0)
|
|
||||||
snmp_log("sk_send OK!");
|
|
||||||
else if (ret == 0)
|
|
||||||
snmp_log("sk_send sleep");
|
|
||||||
else
|
|
||||||
snmp_log("sk_send error");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Register-PDU */
|
/* Register-PDU */
|
||||||
@ -343,15 +325,62 @@ close_pdu(struct snmp_proto *p, u8 reason)
|
|||||||
uint s = update_packet_size(p, buf, c.buffer);
|
uint s = update_packet_size(p, buf, c.buffer);
|
||||||
|
|
||||||
//snmp_log("preparing to sk_send() (close)");
|
//snmp_log("preparing to sk_send() (close)");
|
||||||
int ret = sk_send(sk, s);
|
sk_send(sk, s);
|
||||||
if (ret > 0)
|
|
||||||
snmp_log("sk_send OK!");
|
|
||||||
else if (ret == 0)
|
|
||||||
snmp_log("sk_send sleep");
|
|
||||||
else
|
|
||||||
snmp_log("sk_send error");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint UNUSED
|
||||||
|
parse_close_pdu(struct snmp_proto UNUSED *p, byte UNUSED *req, uint UNUSED size)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
snmp_log("parse_close_pdu()");
|
||||||
|
|
||||||
|
// byte *pkt = req;
|
||||||
|
// sock *sk = p->sock;
|
||||||
|
|
||||||
|
if (size < sizeof(struct agentx_header))
|
||||||
|
{
|
||||||
|
snmp_log("p_close early return");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// struct agentx_header *h = (void *) req;
|
||||||
|
ADVANCE(req, size, AGENTX_HEADER_SIZE);
|
||||||
|
//snmp_log("after header %p", req);
|
||||||
|
|
||||||
|
p->state = SNMP_ERR;
|
||||||
|
|
||||||
|
// or snmp_cleanup(); // ??!
|
||||||
|
proto_notify_state(&p->p, PS_DOWN);
|
||||||
|
*/
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* MUCH better signature would be
|
||||||
|
static int snmp_testset(struct snmp_proto *p, const struct agentx_varbind *vb, uint pkt_size);
|
||||||
|
*/
|
||||||
|
/* return 1 if the value could be set */
|
||||||
|
static int
|
||||||
|
snmp_testset(struct snmp_proto *p, const struct agentx_varbind *vb, struct oid *oid, uint pkt_size)
|
||||||
|
{
|
||||||
|
/* Hard-coded no support for writing */
|
||||||
|
(void)p;(void)vb;(void)oid;(void)pkt_size;
|
||||||
|
return 0;
|
||||||
|
#if 0
|
||||||
|
// TODO better logic
|
||||||
|
if (!oid)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
switch (oid->ids[1])
|
||||||
|
{
|
||||||
|
case SNMP_BGP4_MIB:
|
||||||
|
return snmp_bgp_testset(p, vb, oid, pkt_size);
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
static void UNUSED
|
static void UNUSED
|
||||||
addagentcaps_pdu(struct snmp_proto *p, struct oid *cap, char *descr,
|
addagentcaps_pdu(struct snmp_proto *p, struct oid *cap, char *descr,
|
||||||
@ -394,13 +423,7 @@ addagentcaps_pdu(struct snmp_proto *p, struct oid *cap, char *descr,
|
|||||||
// make a note in the snmp_proto structure
|
// make a note in the snmp_proto structure
|
||||||
|
|
||||||
//int ret = sk_send(sk, buf - sk->tbuf);
|
//int ret = sk_send(sk, buf - sk->tbuf);
|
||||||
int ret = sk_send(sk, buf - sk->tpos);
|
sk_send(sk, buf - sk->tpos);
|
||||||
if (ret == 0)
|
|
||||||
snmp_log("sk_send sleep");
|
|
||||||
else if (ret < 0)
|
|
||||||
snmp_log("sk_send err");
|
|
||||||
else
|
|
||||||
log(L_INFO, "sk_send ok !!");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void UNUSED
|
static void UNUSED
|
||||||
@ -438,14 +461,7 @@ removeagentcaps_pdu(struct snmp_proto *p, struct oid *cap, struct agentx_context
|
|||||||
|
|
||||||
// update state in snmp_proto structure
|
// update state in snmp_proto structure
|
||||||
|
|
||||||
//int ret = sk_send(sk, buf - sk->tbuf);
|
sk_send(sk, buf - sk->tpos);
|
||||||
int ret = sk_send(sk, buf - sk->tpos);
|
|
||||||
if (ret == 0)
|
|
||||||
snmp_log("sk_send sleep");
|
|
||||||
else if (ret < 0)
|
|
||||||
snmp_log("sk_send err");
|
|
||||||
else
|
|
||||||
log(L_INFO, "sk_send ok !!");
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -457,6 +473,194 @@ refresh_ids(struct snmp_proto *p, struct agentx_header *h)
|
|||||||
p->packet_id = LOAD_U32(h->packet_id, byte_ord);
|
p->packet_id = LOAD_U32(h->packet_id, byte_ord);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint
|
||||||
|
parse_test_set_pdu(struct snmp_proto *p, byte *pkt, uint size)
|
||||||
|
{
|
||||||
|
//snmp_log("parse_test_set");
|
||||||
|
const byte *pkt_start = pkt; /* start of packet in RX-buffer */
|
||||||
|
uint ind = 0; /* index of the error */
|
||||||
|
uint s; /* final packat size */
|
||||||
|
struct agentx_response *res; /* pointer to reponse in TX-buffer */
|
||||||
|
|
||||||
|
struct agentx_header *h = (void *) pkt;
|
||||||
|
ADVANCE(pkt, size, AGENTX_HEADER_SIZE);
|
||||||
|
uint pkt_size = LOAD_U32(h->payload, h->flags & AGENTX_NETWORK_BYTE_ORDER);
|
||||||
|
|
||||||
|
sock *sk = p->sock;
|
||||||
|
struct snmp_pdu c = SNMP_PDU_CONTEXT(sk);
|
||||||
|
byte *buf = c.buffer; /* start of packet in TX-buffer */
|
||||||
|
c.byte_ord = 0; /* use little-endian */
|
||||||
|
|
||||||
|
if (c.size < AGENTX_HEADER_SIZE)
|
||||||
|
{
|
||||||
|
snmp_manage_tbuf(p, &c);
|
||||||
|
// TODO renew all pointers
|
||||||
|
}
|
||||||
|
|
||||||
|
res = prepare_response(p, &c);
|
||||||
|
|
||||||
|
uint clen;
|
||||||
|
const char *context;
|
||||||
|
SNMP_LOAD_CONTEXT(h, pkt, context, clen);
|
||||||
|
|
||||||
|
if (size < clen)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (pkt_size < clen)
|
||||||
|
{
|
||||||
|
c.error = AGENTX_RES_PARSE_ERROR;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
ADVANCE(pkt, pkt_size, clen);
|
||||||
|
size -= clen;
|
||||||
|
|
||||||
|
//snmp_log("test_set: parsed header and context");
|
||||||
|
/* 0 if there is piece, that we cannot set */
|
||||||
|
int all_possible = 0;
|
||||||
|
/* the all_possible is currently hard-coded with no support for writing to mib
|
||||||
|
* variables, when implementing the mentioned support, change the initializer
|
||||||
|
* to 1
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// TODO think about future value setting data structure
|
||||||
|
//struct agentx_transaction *tr = mb_alloc(...);
|
||||||
|
void *tr = mb_alloc(p->pool, 16);
|
||||||
|
|
||||||
|
struct agentx_varbind *vb;
|
||||||
|
uint sz;
|
||||||
|
while (size > 0 && all_possible)
|
||||||
|
{
|
||||||
|
vb = (void *) pkt;
|
||||||
|
sz = snmp_varbind_size(vb, 0);
|
||||||
|
|
||||||
|
if (sz > size)
|
||||||
|
/* wait for more data to arive */
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (sz > pkt_size)
|
||||||
|
{
|
||||||
|
c.error = AGENTX_RES_PARSE_ERROR;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unknown VarBind type check */
|
||||||
|
if (!snmp_test_varbind(vb))
|
||||||
|
{
|
||||||
|
c.error = AGENTX_RES_PARSE_ERROR;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
ADVANCE(pkt, size, snmp_varbind_size(vb, 0));
|
||||||
|
|
||||||
|
// TODO remove the mb_alloc() in prefixize()
|
||||||
|
struct oid *work = snmp_prefixize(p, &vb->name, c.byte_ord);
|
||||||
|
(void)work;
|
||||||
|
all_possible = snmp_testset(p, vb, tr, work, pkt_size);
|
||||||
|
mb_free(work);
|
||||||
|
}
|
||||||
|
//snmp_log("test_set parsed all varbinds");
|
||||||
|
mb_free(tr);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
error:
|
||||||
|
s = update_packet_size(p, buf, c.buffer);
|
||||||
|
|
||||||
|
if (c.error != AGENTX_RES_NO_ERROR)
|
||||||
|
response_err_ind(res, c.error, ind + 1);
|
||||||
|
else if (all_possible)
|
||||||
|
response_err_ind(res, AGENTX_RES_NO_ERROR, 0);
|
||||||
|
else
|
||||||
|
//response_err_ind(res, AGENTX_RES_RESOURCE_UNAVAILABLE, ind + 1);
|
||||||
|
response_err_ind(res, AGENTX_RES_NOT_WRITABLE, ind + 1);
|
||||||
|
|
||||||
|
//snmp_log("test_set sending response");
|
||||||
|
sk_send(sk, s);
|
||||||
|
return pkt - pkt_start;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint
|
||||||
|
parse_set_pdu(struct snmp_proto *p, byte *pkt, uint size, uint err)
|
||||||
|
{
|
||||||
|
const byte *pkt_start = pkt;
|
||||||
|
|
||||||
|
if (size < AGENTX_HEADER_SIZE)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
struct agentx_header *h = (void *) pkt;
|
||||||
|
ADVANCE(pkt, size, AGENTX_HEADER_SIZE);
|
||||||
|
uint pkt_size = LOAD_U32(h->payload, h->flags & AGENTX_NETWORK_BYTE_ORDER);
|
||||||
|
|
||||||
|
struct snmp_pdu c = SNMP_PDU_CONTEXT(p->sock);
|
||||||
|
if (c.size < sizeof(struct agentx_response))
|
||||||
|
{
|
||||||
|
snmp_manage_tbuf(p, &c);
|
||||||
|
// TODO renew all pointers
|
||||||
|
}
|
||||||
|
|
||||||
|
struct agentx_response *r = prepare_response(p, &c);
|
||||||
|
|
||||||
|
uint clen;
|
||||||
|
const char *context;
|
||||||
|
SNMP_LOAD_CONTEXT(h, pkt, context, clen);
|
||||||
|
|
||||||
|
if (size < snmp_str_size_from_len(clen))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (size < pkt_size)
|
||||||
|
{
|
||||||
|
c.error = AGENTX_RES_PARSE_ERROR;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
ADVANCE(pkt, size, snmp_str_size_from_len(clen));
|
||||||
|
// TODO: work with context
|
||||||
|
|
||||||
|
// TODO: free resource allocated by parse_test_set_pdu()
|
||||||
|
// TODO: do something meaningful
|
||||||
|
//mb_free(tr);
|
||||||
|
c.error = err;
|
||||||
|
|
||||||
|
error:;
|
||||||
|
response_err_ind(r, c.error, 0);
|
||||||
|
sk_send(p->sock, AGENTX_HEADER_SIZE);
|
||||||
|
return pkt - pkt_start;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* agentx-CommitSet-PDU */
|
||||||
|
static uint
|
||||||
|
parse_commit_set_pdu(struct snmp_proto *p, byte *pkt, uint size)
|
||||||
|
{
|
||||||
|
// don't forget to free resoures allocated by parse_test_set_pdu()
|
||||||
|
//mb_free(tr);
|
||||||
|
return parse_set_pdu(p, pkt, size, AGENTX_RES_COMMIT_FAILED);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* agentx-UndoSet-PDU */
|
||||||
|
static uint
|
||||||
|
parse_undo_set_pdu(struct snmp_proto *p, byte *pkt, uint size)
|
||||||
|
{
|
||||||
|
// don't forget to free resources allocated by parse_test_set_pdu()
|
||||||
|
//mb_free(tr);
|
||||||
|
return parse_set_pdu(p, pkt, size, AGENTX_RES_UNDO_FAILED);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* agentx-CleanupSet-PDU */
|
||||||
|
static uint
|
||||||
|
parse_cleanup_set_pdu(struct snmp_proto *p, byte *pkt, uint size)
|
||||||
|
{
|
||||||
|
// don't forget to free resources allocated by parse_test_set_pdu()
|
||||||
|
//mb_free(tr);
|
||||||
|
|
||||||
|
if (size < AGENTX_HEADER_SIZE)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
struct agentx_header *h = (void *) pkt;
|
||||||
|
return LOAD_U32(h->payload, h->flags & AGENTX_NETWORK_BYTE_ORDER);
|
||||||
|
|
||||||
|
/* No agentx-Response-PDU is sent in response to agentx-CleanupSet-PDU */
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* parse_pkt - parse recieved response packet
|
* parse_pkt - parse recieved response packet
|
||||||
* @p:
|
* @p:
|
||||||
@ -474,7 +678,6 @@ parse_pkt(struct snmp_proto *p, byte *pkt, uint size, uint *skip)
|
|||||||
if (size < AGENTX_HEADER_SIZE)
|
if (size < AGENTX_HEADER_SIZE)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
uint parsed_len = 0;
|
|
||||||
struct agentx_header *h = (void *) pkt;
|
struct agentx_header *h = (void *) pkt;
|
||||||
|
|
||||||
//snmp_log("parse_pkt got type %s (%d)", snmp_pkt_type[h->type], h->type);
|
//snmp_log("parse_pkt got type %s (%d)", snmp_pkt_type[h->type], h->type);
|
||||||
@ -484,33 +687,58 @@ parse_pkt(struct snmp_proto *p, byte *pkt, uint size, uint *skip)
|
|||||||
{
|
{
|
||||||
case AGENTX_RESPONSE_PDU:
|
case AGENTX_RESPONSE_PDU:
|
||||||
//snmp_log("parse_pkt returning parse_response");
|
//snmp_log("parse_pkt returning parse_response");
|
||||||
parsed_len = parse_response(p, pkt, size);
|
return parse_response(p, pkt, size);
|
||||||
break;
|
|
||||||
|
|
||||||
case AGENTX_GET_PDU:
|
case AGENTX_GET_PDU:
|
||||||
case AGENTX_GET_NEXT_PDU:
|
case AGENTX_GET_NEXT_PDU:
|
||||||
case AGENTX_GET_BULK_PDU:
|
case AGENTX_GET_BULK_PDU:
|
||||||
refresh_ids(p, h);
|
refresh_ids(p, h);
|
||||||
parsed_len = parse_gets2_pdu(p, pkt, size, skip);
|
return parse_gets2_pdu(p, pkt, size, skip);
|
||||||
break;
|
|
||||||
|
|
||||||
/* during testing the connection should stay opened (we die if we screw up
|
|
||||||
* and get CLOSE_PDU in response)
|
|
||||||
|
|
||||||
case AGENTX_CLOSE_PDU:
|
case AGENTX_CLOSE_PDU:
|
||||||
refresh_ids(p, h);
|
refresh_ids(p, h);
|
||||||
parsed_len = parse_close_pdu(p, pkt, size);
|
return parse_close_pdu(p, pkt, size);
|
||||||
break;
|
|
||||||
*/
|
case AGENTX_TEST_SET_PDU:
|
||||||
|
refresh_ids(p, h);
|
||||||
|
return parse_test_set_pdu(p, pkt, size);
|
||||||
|
|
||||||
|
case AGENTX_COMMIT_SET_PDU:
|
||||||
|
refresh_ids(p, h);
|
||||||
|
return parse_commit_set_pdu(p, pkt, size);
|
||||||
|
|
||||||
|
case AGENTX_UNDO_SET_PDU:
|
||||||
|
refresh_ids(p, h);
|
||||||
|
return parse_undo_set_pdu(p, pkt, size);
|
||||||
|
|
||||||
|
case AGENTX_CLEANUP_SET_PDU:
|
||||||
|
refresh_ids(p, h);
|
||||||
|
return parse_cleanup_set_pdu(p, pkt, size);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
/* drop the packet with unknown type silently */
|
/* drop the packet with unknown type silently */
|
||||||
//snmp_log("unknown packet type %u", h->type);
|
//snmp_log("unknown packet type %u", h->type);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//snmp_log("parse_pkt returning parsed length");
|
static void
|
||||||
return parsed_len;
|
snmp_register_ok(struct snmp_proto *p, struct agentx_response *r, uint size, u8 type)
|
||||||
|
{
|
||||||
|
(void)p;(void)r;(void)size;(void)type;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
snmp_register_failed(struct snmp_proto *p, struct agentx_response *r, uint size, u8 type)
|
||||||
|
{
|
||||||
|
(void)p;(void)r;(void)size;(void)type;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
unsupported_context(struct snmp_proto *p, struct agentx_response *r, uint size)
|
||||||
|
{
|
||||||
|
(void)p;(void)r;(void)size;
|
||||||
|
// TODO unsupported_context
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint
|
static uint
|
||||||
@ -543,13 +771,58 @@ parse_response(struct snmp_proto *p, byte *res, uint size)
|
|||||||
*/
|
*/
|
||||||
//snmp_log(" pkt size %u", h->payload);
|
//snmp_log(" pkt size %u", h->payload);
|
||||||
|
|
||||||
//snmp_log(" pkt size %u", h->payload);
|
switch (r->error)
|
||||||
|
{
|
||||||
|
case AGENTX_RES_NO_ERROR:
|
||||||
|
do_response(p, res, size);
|
||||||
|
break;
|
||||||
|
|
||||||
if (r->error == AGENTX_RES_NO_ERROR)
|
case AGENTX_RES_NOT_OPEN:
|
||||||
do_response(p, res, size);
|
if (p->state == SNMP_LOCKED || p->state == SNMP_INIT)
|
||||||
else
|
snmp_startup(p);
|
||||||
/* erronous packet should be dropped quietly */
|
else
|
||||||
{}//snmp_log("an error occured '%s'", snmp_errs[get_u16(&r->error) - SNMP_ERR_SHIFT]);
|
snmp_connected(p->sock);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AGENTX_RES_OPEN_FAILED:
|
||||||
|
if (p->state == SNMP_LOCKED || p->state == SNMP_INIT)
|
||||||
|
{
|
||||||
|
ASSUME(p->startup_timer);
|
||||||
|
p->startup_timer->hook = snmp_startup_timeout;
|
||||||
|
// TODO: better timeout
|
||||||
|
tm_set(p->startup_timer, current_time() + p->timeout S);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ASSUME(p->startup_timer);
|
||||||
|
p->startup_timer->hook = snmp_reconnect;
|
||||||
|
// TODO: better timeout
|
||||||
|
tm_set(p->startup_timer, current_time() + p->timeout S);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Registration errors */
|
||||||
|
case AGENTX_RES_DUPLICATE_REGISTER:
|
||||||
|
case AGENTX_RES_REQUEST_DENIED:
|
||||||
|
snmp_register_failed(p, r, size, h->type);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AGENTX_RES_UNSUPPORTED_CONTEXT:
|
||||||
|
unsupported_context(p, r, size);
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* We are trying to unregister a MIB, the unknownRegistration has same
|
||||||
|
* effect as success */
|
||||||
|
case AGENTX_RES_UNKNOWN_REGISTER:
|
||||||
|
case AGENTX_RES_UNKNOWN_AGENT_CAPS:
|
||||||
|
case AGENTX_RES_PARSE_ERROR:
|
||||||
|
case AGENTX_RES_PROCESSING_ERR:
|
||||||
|
default:
|
||||||
|
/* erronous packet should be dropped quietly */
|
||||||
|
// TODO correct error?
|
||||||
|
snmp_log("recieved response with error '%s'", snmp_errs[get_u16(&r->error) - SNMP_ERR_SHIFT]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
return pkt_size + AGENTX_HEADER_SIZE;
|
return pkt_size + AGENTX_HEADER_SIZE;
|
||||||
}
|
}
|
||||||
@ -878,7 +1151,7 @@ parse_gets2_pdu(struct snmp_proto *p, byte * const pkt_start, uint size, uint *s
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!p->partial_response && c.size < sizeof(struct agentx_response))
|
if (c.size < sizeof(struct agentx_response))
|
||||||
{
|
{
|
||||||
snmp_manage_tbuf(p, &c);
|
snmp_manage_tbuf(p, &c);
|
||||||
// TODO renew pkt, pkt_start pointers context clen
|
// TODO renew pkt, pkt_start pointers context clen
|
||||||
@ -1024,17 +1297,9 @@ send:;
|
|||||||
//snmp_log("sending response to Get-PDU, GetNext-PDU or GetBulk-PDU request (size %u)...", s);
|
//snmp_log("sending response to Get-PDU, GetNext-PDU or GetBulk-PDU request (size %u)...", s);
|
||||||
|
|
||||||
/* We send the message in TX-buffer. */
|
/* We send the message in TX-buffer. */
|
||||||
int ret = sk_send(sk, s);
|
sk_send(sk, s);
|
||||||
if (ret > 0)
|
|
||||||
snmp_log("sk_send OK!");
|
|
||||||
else if (ret == 0)
|
|
||||||
snmp_log("sk_send sleep");
|
|
||||||
else
|
|
||||||
snmp_log("sk_send error");
|
|
||||||
// TODO think through the error state
|
// TODO think through the error state
|
||||||
|
|
||||||
p->partial_response = NULL;
|
|
||||||
|
|
||||||
mb_free(o_start);
|
mb_free(o_start);
|
||||||
mb_free(o_end);
|
mb_free(o_end);
|
||||||
|
|
||||||
@ -1051,7 +1316,6 @@ partial:
|
|||||||
(c.byte_ord) ? put_u32(&h->payload, pkt_size) : (h->payload = pkt_size);
|
(c.byte_ord) ? put_u32(&h->payload, pkt_size) : (h->payload = pkt_size);
|
||||||
//snmp_log("new rx-buffer size %u", h->payload);
|
//snmp_log("new rx-buffer size %u", h->payload);
|
||||||
*skip = AGENTX_HEADER_SIZE;
|
*skip = AGENTX_HEADER_SIZE;
|
||||||
p->partial_response = response_header;
|
|
||||||
|
|
||||||
/* number of bytes parsed from RX-buffer */
|
/* number of bytes parsed from RX-buffer */
|
||||||
return pkt - pkt_start;
|
return pkt - pkt_start;
|
||||||
@ -1176,13 +1440,7 @@ snmp_ping(struct snmp_proto *p)
|
|||||||
/* 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);
|
||||||
|
|
||||||
int ret = sk_send(sk, s);
|
sk_send(sk, s);
|
||||||
if (ret > 0)
|
|
||||||
snmp_log("sk_send OK!");
|
|
||||||
else if (ret == 0)
|
|
||||||
snmp_log("sk_send sleep");
|
|
||||||
else
|
|
||||||
snmp_log("sk_send error");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
@ -1396,24 +1654,19 @@ prepare_response(struct snmp_proto *p, struct snmp_pdu *c)
|
|||||||
{
|
{
|
||||||
//snmp_log("prepare_response()");
|
//snmp_log("prepare_response()");
|
||||||
|
|
||||||
if (!p->partial_response)
|
struct agentx_response *r = (void *) c->buffer;
|
||||||
{
|
struct agentx_header *h = &r->h;
|
||||||
struct agentx_response *r = (void *) c->buffer;
|
|
||||||
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(h, p);
|
||||||
|
|
||||||
/* protocol doesn't care about subagent upTime */
|
/* protocol doesn't care about subagent upTime */
|
||||||
STORE_U32(r->uptime, 0);
|
STORE_U32(r->uptime, 0);
|
||||||
STORE_U16(r->error, AGENTX_RES_NO_ERROR);
|
STORE_U16(r->error, AGENTX_RES_NO_ERROR);
|
||||||
STORE_U16(r->index, 0);
|
STORE_U16(r->index, 0);
|
||||||
|
|
||||||
ADVANCE(c->buffer, c->size, sizeof(struct agentx_response));
|
ADVANCE(c->buffer, c->size, sizeof(struct agentx_response));
|
||||||
return r;
|
return r;
|
||||||
}
|
|
||||||
|
|
||||||
return p->partial_response;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -122,7 +122,7 @@ enum snmp_search_res {
|
|||||||
buf += 4 + snmp_str_size_from_len(length); })
|
buf += 4 + snmp_str_size_from_len(length); })
|
||||||
|
|
||||||
#define SNMP_LOAD_CONTEXT(hdr, buf, cont, cont_len) ({ \
|
#define SNMP_LOAD_CONTEXT(hdr, buf, cont, cont_len) ({ \
|
||||||
if ((hdr)->flags & AGENTX_NON_DEFAULT_CONTEXT) \
|
if (cont = NULL, cont_len = 0, (hdr)->flags & AGENTX_NON_DEFAULT_CONTEXT) \
|
||||||
LOAD_STR((buf), (cont), (cont_len), \
|
LOAD_STR((buf), (cont), (cont_len), \
|
||||||
(hdr)->flags & AGENTX_NETWORK_BYTE_ORDER); })
|
(hdr)->flags & AGENTX_NETWORK_BYTE_ORDER); })
|
||||||
|
|
||||||
@ -289,7 +289,9 @@ enum agentx_response_err {
|
|||||||
AGENTX_RES_NO_CREATION = 11,
|
AGENTX_RES_NO_CREATION = 11,
|
||||||
AGENTX_RES_INCONSISTENT_VALUE = 12,
|
AGENTX_RES_INCONSISTENT_VALUE = 12,
|
||||||
AGENTX_RES_RESOURCE_UNAVAILABLE = 13,
|
AGENTX_RES_RESOURCE_UNAVAILABLE = 13,
|
||||||
AGENTX_RES_NOT_WRITEABLE = 17,
|
AGENTX_RES_COMMIT_FAILED = 14,
|
||||||
|
AGENTX_RES_UNDO_FAILED = 15,
|
||||||
|
AGENTX_RES_NOT_WRITABLE = 17,
|
||||||
AGENTX_RES_INCONSISTENT_NAME = 18,
|
AGENTX_RES_INCONSISTENT_NAME = 18,
|
||||||
/* end of TEST_SET_PDU resonse errs (master -> subagent) */
|
/* end of TEST_SET_PDU resonse errs (master -> subagent) */
|
||||||
AGENTX_RES_OPEN_FAILED = 256,
|
AGENTX_RES_OPEN_FAILED = 256,
|
||||||
|
Loading…
Reference in New Issue
Block a user