diff --git a/proto/snmp/bgp_mib.c b/proto/snmp/bgp_mib.c index c6c5ce50..4e62d29c 100644 --- a/proto/snmp/bgp_mib.c +++ b/proto/snmp/bgp_mib.c @@ -71,7 +71,7 @@ snmp_bgp_register(struct snmp_proto *p) add_tail(&p->register_queue, ®istering->n); p->register_to_ack++; - snmp_register(p, oid, 0, 1); + snmp_register(p, oid, 0, 1, 0); } /* diff --git a/proto/snmp/snmp.c b/proto/snmp/snmp.c index d958722a..11b42a45 100644 --- a/proto/snmp/snmp.c +++ b/proto/snmp/snmp.c @@ -65,24 +65,16 @@ snmp_init(struct proto_config *CF) static inline void snmp_cleanup(struct snmp_proto *p) { - struct additional_buffer *b; - WALK_LIST(b, p->additional_buffers) - { - mb_free(b->buf); - rem_node(&b->n); - mb_free(b); - } - init_list(&p->additional_buffers); - rfree(p->startup_timer); - rfree(p->ping_timer); + p->startup_timer = NULL; - if (p->sock != NULL) - rfree(p->sock); + rfree(p->ping_timer); + p->ping_timer = NULL; + + rfree(p->sock); p->sock = NULL; - if (p->lock != NULL) - rfree(p->lock); + rfree(p->lock); p->lock = NULL; p->state = SNMP_DOWN; @@ -172,14 +164,13 @@ snmp_start_locked(struct object_lock *lock) s->tx_hook = snmp_connected; s->err_hook = snmp_sock_err; + //mb_free(p->sock); p->sock = s; s->data = p; p->to_send = 0; p->errs = 0; - // snmp_startup(p); - if (sk_open(s) < 0) { log(L_ERR "Cannot open listening socket"); @@ -195,8 +186,6 @@ snmp_connected(sock *sk) struct snmp_proto *p = sk->data; snmp_log("snmp_connected() connection created"); byte *buf UNUSED = sk->rpos; - uint size = sk->rbuf + sk->rbsize - sk->rpos; - snmp_dump_packet(buf, size); sk->rx_hook = snmp_rx; sk->tx_hook = snmp_tx; @@ -223,13 +212,8 @@ snmp_sock_err(sock *sk, int err) p->lock = NULL; snmp_log("changing proto_snmp state to ERR[OR]"); - if (err) - p->state = SNMP_ERR; - else - { - snmp_shutdown((struct proto *) p); - return; - } + p->state = SNMP_ERR; + // snmp_shutdown((struct proto *) p); // TODO ping interval tm_start(p->startup_timer, 4 S); @@ -252,29 +236,11 @@ snmp_start(struct proto *P) init_list(&p->register_queue); init_list(&p->bgp_registered); + p->partial_response = NULL; p->ping_timer = tm_new_init(p->p.pool, snmp_ping_timer, p, 0, 0); // tm_set(p->ping_timer, current_time() + 2 S); -/* remove duplicate lock acquiring code */ -#if 0 - /* starting agentX communicaiton channel */ - snmp_log("preparing lock"); - struct object_lock *lock; - lock = p->lock = olock_new(p->p.pool); - - lock->type = OBJLOCK_TCP; - lock->hook = snmp_start_locked; - lock->data = p; - - olock_acquire(lock); - snmp_log("lock acquired"); - - snmp_log("local ip: %I:%u, remote ip: %I:%u", - p->local_ip, p->local_port, p->remote_ip, p->remote_port); - -#endif - /* create copy of bonds to bgp */ HASH_INIT(p->bgp_hash, p->p.pool, 10); @@ -298,8 +264,6 @@ snmp_start(struct proto *P) } } - init_list(&p->additional_buffers); - snmp_startup(p); return PS_START; } diff --git a/proto/snmp/snmp.h b/proto/snmp/snmp.h index 21d777d2..0c767a7b 100644 --- a/proto/snmp/snmp.h +++ b/proto/snmp/snmp.h @@ -26,8 +26,8 @@ #define SNMP_PORT 705 -#define SNMP_RX_BUFFER_SIZE 2048 -#define SNMP_TX_BUFFER_SIZE 2048 +#define SNMP_RX_BUFFER_SIZE 8192 +#define SNMP_TX_BUFFER_SIZE 8192 enum snmp_proto_state { SNMP_ERR = 0, @@ -129,8 +129,11 @@ struct snmp_proto { uint to_send; uint errs; - list additional_buffers; /* buffers of data to send that does not fit - * into socket's TX buffer */ + /* + * 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); diff --git a/proto/snmp/subagent.c b/proto/snmp/subagent.c index bd31a5cd..f0241392 100644 --- a/proto/snmp/subagent.c +++ b/proto/snmp/subagent.c @@ -43,13 +43,12 @@ static struct agentx_response *prepare_response(struct snmp_proto *p, struct snm //static byte *prepare_response(struct snmp_proto *p, struct snmp_pdu_context *c); //static struct agentx_response *prepare_response(struct snmp_proto *p, byte *buf, uint size); static void response_err_ind(struct agentx_response *res, uint err, uint ind); -static void update_packet_size(struct snmp_proto *p, struct agentx_header *h, byte *start, byte *end); +static uint update_packet_size(struct snmp_proto *p, byte *start, byte *end); //static void response_err_ind(byte *buf, uint err, uint ind); //static struct oid *search_mib(struct snmp_proto *p, struct oid *o_start, struct oid *o_end, struct oid *o_curr, u8 mib_class, struct snmp_pdu_context *c); static struct oid *search_mib(struct snmp_proto *p, const struct oid *o_start, const struct oid *o_end, struct oid *o_curr, struct snmp_pdu_context *c, enum snmp_search_res *result); //static struct oid *search_mib(struct snmp_proto *p, struct oid *o_start, struct oid *o_end, struct oid *o_curr, u8 mib_class, uint contid); // static inline byte *find_n_fill(struct snmp_proto *p, struct oid *o, byte *buf, uint size, uint contid, int byte_ord); -int snmp_send(struct snmp_proto *p, struct snmp_pdu_context *c); static const char * const snmp_errs[] = { #define SNMP_ERR_SHIFT 256 @@ -109,24 +108,28 @@ open_pdu(struct snmp_proto *p, struct oid *oid) buf = c.buffer; } - c.size -= (AGENTX_HEADER_SIZE + snmp_oid_size(oid) + snmp_str_size(str) + 4); - snmp_log("open_pdu()"); - struct agentx_header *h = (struct agentx_header *) c.buffer; + ADVANCE(c.buffer, c.size, AGENTX_HEADER_SIZE); SNMP_BLANK_HEADER(h, AGENTX_OPEN_PDU); STORE_U32(h->session_id, 1); STORE_U32(h->transaction_id, 1); STORE_U32(h->packet_id, 1); + c.size -= (4 + snmp_oid_size(oid) + snmp_str_size(str)); c.buffer = snmp_put_fbyte(c.buffer, p->timeout); c.buffer = snmp_put_oid(c.buffer, oid); c.buffer = snmp_put_str(c.buffer, str); - update_packet_size(p, h, buf, c.buffer); - snmp_log("send PDU data (open) ..."); - snmp_send(p, &c); + uint s = update_packet_size(p, buf, c.buffer); + int ret = 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"); } #if 0 @@ -241,9 +244,9 @@ de_allocate_pdu(struct snmp_proto *p, struct oid *oid, u8 type) } */ -/* register / unregister pdu */ -static void -un_register_pdu(struct snmp_proto *p, struct oid *oid, uint index, uint len, u8 type) +/* Register-PDU / Unregister-PDU */ +static inline void +un_register_pdu(struct snmp_proto *p, struct oid *oid, uint index, uint len, u8 type, u8 is_instance) { sock *sk = p->sock; //buf = pkt = sk->tbuf; @@ -268,10 +271,9 @@ un_register_pdu(struct snmp_proto *p, struct oid *oid, uint index, uint len, u8 struct agentx_header *h = &ur->h; // FIXME correctly set INSTANCE REGISTRATION bit - SNMP_HEADER(h, type, AGENTX_FLAG_INSTANCE_REGISTRATION); + SNMP_HEADER(h, type, is_instance ? AGENTX_FLAG_INSTANCE_REGISTRATION : 0); /* use new transactionID, reset packetID */ - p->transaction_id++; - p->packet_id = 1; + p->packet_id++; SNMP_SESSION(h, p); /* do not override timeout */ @@ -292,22 +294,29 @@ un_register_pdu(struct snmp_proto *p, struct oid *oid, uint index, uint len, u8 } /* buf - start, pkt - end */ - update_packet_size(p, h, buf, c.buffer); + update_packet_size(p, buf, c.buffer); /* for (uint i = 0; i < pkt - buf; i++) snmp_log("%p: %02X", buf+i, *(buf + i)); */ + uint s = update_packet_size(p, buf, c.buffer); snmp_log("sending (un)register %s", snmp_pkt_type[type]); - snmp_send(p, &c); + int ret = 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 */ void -snmp_register(struct snmp_proto *p, struct oid *oid, uint index, uint len) +snmp_register(struct snmp_proto *p, struct oid *oid, uint index, uint len, u8 is_instance) { - un_register_pdu(p, oid, index, len, AGENTX_REGISTER_PDU); + un_register_pdu(p, oid, index, len, AGENTX_REGISTER_PDU, is_instance); } @@ -315,7 +324,7 @@ snmp_register(struct snmp_proto *p, struct oid *oid, uint index, uint len) void UNUSED snmp_unregister(struct snmp_proto *p, struct oid *oid, uint index, uint len) { - un_register_pdu(p, oid, index, len, AGENTX_UNREGISTER_PDU); + un_register_pdu(p, oid, index, len, AGENTX_UNREGISTER_PDU, 0); } static void @@ -341,15 +350,22 @@ close_pdu(struct snmp_proto *p, u8 reason) struct agentx_header *h = (struct agentx_header *) c.buffer; ADVANCE(c.buffer, c.size, AGENTX_HEADER_SIZE); SNMP_BLANK_HEADER(h, AGENTX_CLOSE_PDU); + p->packet_id++; SNMP_SESSION(h, p); snmp_put_fbyte(c.buffer, reason); ADVANCE(c.buffer, c.size, 4); - update_packet_size(p, h, buf, c.buffer); + uint s = update_packet_size(p, buf, c.buffer); snmp_log("preparing to sk_send() (close)"); - snmp_send(p, &c); + int ret = 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"); } #if 0 @@ -481,8 +497,8 @@ static inline void refresh_ids(struct snmp_proto *p, struct agentx_header *h) { int byte_ord = h->flags & AGENTX_NETWORK_BYTE_ORDER; - p->transaction_id = LOAD(h->transaction_id, byte_ord); - p->packet_id = LOAD(h->packet_id, byte_ord); + p->transaction_id = LOAD_U32(h->transaction_id, byte_ord); + p->packet_id = LOAD_U32(h->packet_id, byte_ord); } /** @@ -576,7 +592,7 @@ parse_response(struct snmp_proto *p, byte *res, uint size) int byte_ord = h->flags & AGENTX_NETWORK_BYTE_ORDER; - uint pkt_size = LOAD(h->payload, byte_ord); + uint pkt_size = LOAD_U32(h->payload, byte_ord); snmp_log("p_res pkt_size %u", pkt_size); if (size < pkt_size + AGENTX_HEADER_SIZE) { snmp_log("parse_response early return"); @@ -630,7 +646,7 @@ do_response(struct snmp_proto *p, byte *buf, uint size UNUSED) { case SNMP_INIT: /* copy session info from recieved packet */ - p->session_id = LOAD(h->session_id, byte_ord); + p->session_id = LOAD_U32(h->session_id, byte_ord); refresh_ids(p, h); /* the state needs to be changed before sending registering PDUs to @@ -670,7 +686,7 @@ u8 snmp_get_mib_class(const struct oid *oid) { // TODO check code paths for oid->n_subid < 3 - if (oid->prefix != 2 && oid->ids[0] != 1) + if (oid->prefix != 2 && oid->ids[0] != SNMP_MIB_2) return SNMP_CLASS_INVALID; switch (oid->ids[1]) @@ -865,32 +881,14 @@ parse_close_pdu(struct snmp_proto UNUSED *p, byte UNUSED *req, uint UNUSED size) return 0; } -static inline void -update_packet_size(struct snmp_proto *p, struct agentx_header *h, byte *start, byte *end) +static inline uint +update_packet_size(struct snmp_proto *p, byte *start, byte *end) { - uint size; + struct agentx_header *h = (void *) p->sock->tpos; - if (EMPTY_LIST(p->additional_buffers)) - size = snmp_pkt_len(start, end); - else - size = p->to_send; - - - /* TODO add packet size limiting - * we couldn't overflow the size because we limit the maximum packet size - */ - struct additional_buffer *b; - WALK_LIST(b, p->additional_buffers) - { - size += b->pos - b->buf; - } - - STORE_U32(h->payload, size); - -// if (p->additional_buffers) -// STORE_U32(h->payload, p->to_send + (end - start)); -// else {} -//// STORE_U32(h->payload, snmp_pkt_len(start, end)); + size_t s = snmp_pkt_len(start, end); + STORE_U32(h->payload, s); + return AGENTX_HEADER_SIZE + s; } static inline void @@ -913,7 +911,7 @@ parse_gets2_pdu(struct snmp_proto *p, byte * const pkt_start, uint size, uint *s struct agentx_header *h = (void *) pkt; ADVANCE(pkt, size, AGENTX_HEADER_SIZE); - uint pkt_size = LOAD(h->payload, h->flags & AGENTX_NETWORK_BYTE_ORDER); + uint pkt_size = LOAD_U32(h->payload, h->flags & AGENTX_NETWORK_BYTE_ORDER); sock *sk = p->sock; struct snmp_pdu_context c = { @@ -1074,9 +1072,9 @@ parse_gets2_pdu(struct snmp_proto *p, byte * const pkt_start, uint size, uint *s send: snmp_log("gets2: sending response ..."); - response_err_ind(response_header, c.error, ind); + //response_err_ind(response_header, c.error, ind); // update_packet_size(&response_header->h, sk->tbuf, c.buffer); - update_packet_size(p, &response_header->h, (byte *) response_header, c.buffer); + //update_packet_size(p, &response_header->h, (byte *) response_header, c.buffer); //snmp_dump_packet((byte *) response_header, AGENTX_HEADER_SIZE + LOAD(response_header->h.payload, c.byte_ord)); //snmp_dump_packet((byte *) response_header, AGENTX_HEADER_SIZE + 16 + 8); @@ -1090,33 +1088,41 @@ send: snmp_log("diff %d start byte %u end byte %u", c.buffer - ((byte *) response_header), b, d); */ - + response_err_ind(response_header, c.error, ind); + uint s = update_packet_size(p, (byte *) response_header, c.buffer); /* number of bytes put into the tx-buffer */ //int ret = sk_send(sk, c.buffer - sk->tbuf); snmp_log("sending response to Get-PDU, GetNext-PDU or GetBulk-PDU request ..."); - snmp_send(p, &c); - /* - int ret = sk_send(sk, c.buffer - sk->tpos); + int ret = sk_send(sk, s); if (ret == 0) snmp_log("sk_send sleep (gets2"); else if (ret < 0) snmp_log("sk_send err %d (gets2)", ret); else snmp_log("sk_send was successful (gets2) !"); - */ + + p->partial_response = NULL; mb_free(context); mb_free(o_start); mb_free(o_end); + /* number of bytes parsed form rx-buffer */ return pkt - pkt_start; partial: snmp_log("partial packet"); /* The context octet is not added into response pdu */ + + /* need to tweak RX buffer packet size */ + snmp_log("old rx-buffer size %u", h->payload); + (c.byte_ord) ? put_u32(&h->payload, pkt_size) : (h->payload = pkt_size); + snmp_log("new rx-buffer size %u", h->payload); + *skip = AGENTX_HEADER_SIZE; - goto send; + p->partial_response = response_header; + return pkt - pkt_start; wait: mb_free(context); @@ -1321,7 +1327,7 @@ parse_gets_pdu(struct snmp_proto *p, byte *pkt_start, uint size, uint UNUSED *sk snmp_log(" pasting size"); response_err_ind(response_header, c.error, ind); - update_packet_size(p, &response_header->h, res, c.buffer); + update_packet_size(p, res, c.buffer); snmp_log("ttx %p c.buffer - res %lu", p->sock->ttx, c.buffer - res); snmp_log("c.buffer %p res %p", c.buffer, res); @@ -1403,6 +1409,7 @@ snmp_rx(sock *sk, uint size) struct snmp_proto *p = sk->data; byte *pkt_start = sk->rbuf; byte *end = pkt_start + size; + snmp_log("snmp_rx rbuf 0x%p rpos 0x%p", sk->rbuf, sk->rpos); /* * In some cases we want to save the header for future parsing, skip is number @@ -1459,11 +1466,19 @@ snmp_ping(struct snmp_proto *p) struct agentx_header *h = (struct agentx_header *) c.buffer; ADVANCE(c.buffer, c.size, AGENTX_HEADER_SIZE); SNMP_BLANK_HEADER(h, AGENTX_PING_PDU); + p->packet_id++; SNMP_SESSION(h, p); /* sending only header => pkt - buf */ snmp_log("sending ping packet ..."); - snmp_send(p, &c); + uint s = update_packet_size(p, sk->tpos, c.buffer); + int ret = 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"); } /* @@ -1614,6 +1629,7 @@ search_mib(struct snmp_proto *p, const struct oid *o_start, const struct oid *o_ /* fall through */ default: + if (o_curr) mb_free(o_curr); o_curr = snmp_oid_duplicate(p->p.pool, o_start); *result = SNMP_SEARCH_END_OF_VIEW; break; @@ -1667,7 +1683,7 @@ snmp_prefixize(struct snmp_proto *proto, const struct oid *oid, int byte_ord) { snmp_log("too small"); return NULL; } for (int i = 0; i < 4; i++) - if (LOAD(oid->ids[i], byte_ord) != prefix[i]) + if (LOAD_U32(oid->ids[i], byte_ord) != prefix[i]) { snmp_log("different prefix"); return NULL; } /* validity check here */ @@ -1773,35 +1789,21 @@ void snmp_manage_tbuf(struct snmp_proto *p, struct snmp_pdu_context *c) { snmp_log("snmp_manage_tbuf()"); - - struct additional_buffer *t = TAIL(p->additional_buffers); - t->pos = c->buffer; - - struct additional_buffer *b = mb_alloc(p->p.pool, sizeof(struct additional_buffer)); - b->buf = b->pos = mb_alloc(p->p.pool, SNMP_TX_BUFFER_SIZE); - add_tail(&p->additional_buffers, &b->n); - - c->buffer = b->buf; - c->size = SNMP_TX_BUFFER_SIZE; -} - -int -snmp_send(struct snmp_proto *p, struct snmp_pdu_context *c) -{ sock *sk = p->sock; - if (EMPTY_LIST(p->additional_buffers)) - return sk_send(sk, c->buffer - sk->tpos); - - return sk_send(sk, p->to_send); + sk_set_tbsize(sk , sk->tbsize + 2048); + c->size += 2048; } void snmp_tx(sock *sk) { snmp_log("snmp_tx() hook"); - struct snmp_proto *p = sk->data; + //struct snmp_proto *p = sk->data; + return; + +#if 0 while (!EMPTY_LIST(p->additional_buffers)) { struct additional_buffer *b = HEAD(p->additional_buffers); @@ -1816,6 +1818,7 @@ snmp_tx(sock *sk) if (ret <= 0) return; } +#endif } diff --git a/proto/snmp/subagent.h b/proto/snmp/subagent.h index fa140f93..3a5c8cc5 100644 --- a/proto/snmp/subagent.h +++ b/proto/snmp/subagent.h @@ -55,7 +55,6 @@ enum snmp_search_res { #define AGENTX_ADMIN_START 2 #define AGENTX_PRIORITY 127 -#define MAX_STR 0xFFFFFFFF #define SNMP_NATIVE @@ -76,7 +75,8 @@ enum snmp_search_res { put_u8(&h->version, v); \ put_u8(&h->type, t); \ put_u8(&h->flags, f); \ - put_u8(&h->pad, 0) + 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) @@ -92,8 +92,8 @@ enum snmp_search_res { STORE_U32(h->transaction_id, p->transaction_id); \ STORE_U32(h->packet_id, p->packet_id) -#define LOAD(v, bo) ((bo) ? get_u32(&v) : (u32) (v)) -#define LOAD_16(v, bo) ((bo) ? get_u16(&v) : (u16) (v)) +#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(proto, buf, str, length, byte_order) ({ \ @@ -113,22 +113,16 @@ enum snmp_search_res { #define SNMP_HAS_CONTEXT(hdr) \ hdr->flags |= AGENTX_NON_DEFAULT_CONTEXT -#if 0 - if (h->flags & AGENTX_NON_DEFAULT_CONTEXT) \ - { log(L_INFO "encountered non-default context"); \ - LOAD_STR(p, b, s, l, h->flags & AGENTX_NETWORK_BYTE_ORDER); } -#endif - -#define SNMP_PUT_OID(buf, size, oid, byte_ord) \ - ({ \ - struct agentx_varbind *vb = (void *) buf; \ - SNMP_FILL_VARBIND(vb, oid, byte_ord); \ +#define SNMP_PUT_OID(buf, size, oid, byte_ord) \ + ({ \ + struct agentx_varbind *vb = (void *) buf; \ + SNMP_FILL_VARBIND(vb, oid, byte_ord); \ }) -#define SNMP_FILL_VARBIND(vb, oid, byte_ord) \ +#define SNMP_FILL_VARBIND(vb, oid, byte_ord) \ snmp_oid_copy(&(vb)->name, (oid), (byte_ord)), snmp_oid_size((oid)) - -#define SNMP_VB_DATA(varbind) \ + +#define SNMP_VB_DATA(varbind) \ (((void *)(varbind)) + snmp_varbind_header_size(varbind)) struct agentx_header { @@ -196,11 +190,6 @@ struct agentx_bulk_state { u16 repetition; }; -//struct snmp_error { -// struct oid *oid; -// uint type; -//}; - enum agentx_pdu { AGENTX_OPEN_PDU = 1, AGENTX_CLOSE_PDU = 2, @@ -279,7 +268,7 @@ enum agentx_response_err { struct agentx_context { char *context; /* string name of this context */ uint length; /* normal strlen() size */ - /* add buffered context hash? */ + /* XXX add buffered context hash? */ }; struct snmp_pdu_context { @@ -298,16 +287,19 @@ struct agentx_alloc_context { uint clen; /* length of context string */ }; +#if 0 struct additional_buffer { node n; byte *buf; /* pointer to buffer data */ byte *pos; /* position of first unused byte */ }; +#endif int snmp_rx(sock *sk, uint size); int snmp_rx_stop(sock *sk, uint size); +//int snmp_is_active(int snmp_state); void snmp_down(struct snmp_proto *p); -void snmp_register(struct snmp_proto *p, struct oid *oid, uint index, uint len); +void snmp_register(struct snmp_proto *p, struct oid *oid, uint index, uint len, u8 is_instance); void snmp_unregister(struct snmp_proto *p, struct oid *oid, uint index, uint len); void snmp_manage_tbuf(struct snmp_proto *p, struct snmp_pdu_context *c);