diff --git a/proto/snmp/bgp_mib.c b/proto/snmp/bgp_mib.c index b46772d0..c6c5ce50 100644 --- a/proto/snmp/bgp_mib.c +++ b/proto/snmp/bgp_mib.c @@ -16,38 +16,38 @@ #include "bgp_mib.h" static const char * const debug_bgp_states[] UNUSED = { - [BGP_INTERNAL_INVALID] = "BGP_INTERNAL_INVALID", - [BGP_INTERNAL_BGP] = "BGP_INTERNAL_BGP", - [BGP_INTERNAL_VERSION] = "BGP_INTERNAL_VERSION", - [BGP_INTERNAL_LOCAL_AS] = "BGP_INTERNAL_LOCAL_AS", - [BGP_INTERNAL_PEER_TABLE] = "BGP_INTERNAL_PEER_TABLE", - [BGP_INTERNAL_PEER_ENTRY] = "BGP_INTERNAL_PEER_ENTRY", - [BGP_INTERNAL_IDENTIFIER] = "BGP_INTERNAL_IDENTIFIER", - [BGP_INTERNAL_STATE] = "BGP_INTERNAL_STATE", - [BGP_INTERNAL_ADMIN_STATUS] = "BGP_INTERNAL_ADMIN_STATUS", - [BGP_INTERNAL_NEGOTIATED_VERSION] = "BGP_INTERNAL_NEGOTIATED_VERSION", - [BGP_INTERNAL_LOCAL_ADDR] = "BGP_INTERNAL_LOCAL_ADDR", - [BGP_INTERNAL_LOCAL_PORT] = "BGP_INTERNAL_LOCAL_PORT", - [BGP_INTERNAL_REMOTE_ADDR] = "BGP_INTERNAL_REMOTE_ADDR", - [BGP_INTERNAL_REMOTE_PORT] = "BGP_INTERNAL_REMOTE_PORT", - [BGP_INTERNAL_REMOTE_AS] = "BGP_INTERNAL_REMOTE_AS", - [BGP_INTERNAL_RX_UPDATES] = "BGP_INTERNAL_RX_UPDATES", - [BGP_INTERNAL_TX_UPDATES] = "BGP_INTERNAL_TX_UPDATES", - [BGP_INTERNAL_RX_MESSAGES] = "BGP_INTERNAL_RX_MESSAGES", - [BGP_INTERNAL_TX_MESSAGES] = "BGP_INTERNAL_TX_MESSAGES", - [BGP_INTERNAL_LAST_ERROR] = "BGP_INTERNAL_LAST_ERROR", - [BGP_INTERNAL_FSM_TRANSITIONS] = "BGP_INTERNAL_FSM_TRANSITIONS", - [BGP_INTERNAL_FSM_ESTABLISHED_TIME] = "BGP_INTERNAL_FSM_ESTABLISHED_TIME", - [BGP_INTERNAL_RETRY_INTERVAL] = "BGP_INTERNAL_RETRY_INTERVAL", - [BGP_INTERNAL_HOLD_TIME] = "BGP_INTERNAL_HOLD_TIME", - [BGP_INTERNAL_KEEPALIVE] = "BGP_INTERNAL_KEEPALIVE", - [BGP_INTERNAL_HOLD_TIME_CONFIGURED] = "BGP_INTERNAL_HOLD_TIME_CONFIGURED", - [BGP_INTERNAL_KEEPALIVE_CONFIGURED] = "BGP_INTERNAL_KEEPALIVE_CONFIGURED", - [BGP_INTERNAL_ORIGINATION_INTERVAL] = "BGP_INTERNAL_ORIGINATION_INTERVAL", + [BGP_INTERNAL_INVALID] = "BGP_INTERNAL_INVALID", + [BGP_INTERNAL_BGP] = "BGP_INTERNAL_BGP", + [BGP_INTERNAL_VERSION] = "BGP_INTERNAL_VERSION", + [BGP_INTERNAL_LOCAL_AS] = "BGP_INTERNAL_LOCAL_AS", + [BGP_INTERNAL_PEER_TABLE] = "BGP_INTERNAL_PEER_TABLE", + [BGP_INTERNAL_PEER_ENTRY] = "BGP_INTERNAL_PEER_ENTRY", + [BGP_INTERNAL_IDENTIFIER] = "BGP_INTERNAL_IDENTIFIER", + [BGP_INTERNAL_STATE] = "BGP_INTERNAL_STATE", + [BGP_INTERNAL_ADMIN_STATUS] = "BGP_INTERNAL_ADMIN_STATUS", + [BGP_INTERNAL_NEGOTIATED_VERSION] = "BGP_INTERNAL_NEGOTIATED_VERSION", + [BGP_INTERNAL_LOCAL_ADDR] = "BGP_INTERNAL_LOCAL_ADDR", + [BGP_INTERNAL_LOCAL_PORT] = "BGP_INTERNAL_LOCAL_PORT", + [BGP_INTERNAL_REMOTE_ADDR] = "BGP_INTERNAL_REMOTE_ADDR", + [BGP_INTERNAL_REMOTE_PORT] = "BGP_INTERNAL_REMOTE_PORT", + [BGP_INTERNAL_REMOTE_AS] = "BGP_INTERNAL_REMOTE_AS", + [BGP_INTERNAL_RX_UPDATES] = "BGP_INTERNAL_RX_UPDATES", + [BGP_INTERNAL_TX_UPDATES] = "BGP_INTERNAL_TX_UPDATES", + [BGP_INTERNAL_RX_MESSAGES] = "BGP_INTERNAL_RX_MESSAGES", + [BGP_INTERNAL_TX_MESSAGES] = "BGP_INTERNAL_TX_MESSAGES", + [BGP_INTERNAL_LAST_ERROR] = "BGP_INTERNAL_LAST_ERROR", + [BGP_INTERNAL_FSM_TRANSITIONS] = "BGP_INTERNAL_FSM_TRANSITIONS", + [BGP_INTERNAL_FSM_ESTABLISHED_TIME] = "BGP_INTERNAL_FSM_ESTABLISHED_TIME", + [BGP_INTERNAL_RETRY_INTERVAL] = "BGP_INTERNAL_RETRY_INTERVAL", + [BGP_INTERNAL_HOLD_TIME] = "BGP_INTERNAL_HOLD_TIME", + [BGP_INTERNAL_KEEPALIVE] = "BGP_INTERNAL_KEEPALIVE", + [BGP_INTERNAL_HOLD_TIME_CONFIGURED] = "BGP_INTERNAL_HOLD_TIME_CONFIGURED", + [BGP_INTERNAL_KEEPALIVE_CONFIGURED] = "BGP_INTERNAL_KEEPALIVE_CONFIGURED", + [BGP_INTERNAL_ORIGINATION_INTERVAL] = "BGP_INTERNAL_ORIGINATION_INTERVAL", [BGP_INTERNAL_MIN_ROUTE_ADVERTISEMENT] = "BGP_INTERNAL_MIN_ROUTE_ADVERTISEMENT", - [BGP_INTERNAL_IN_UPDATE_ELAPSED_TIME] = "BGP_INTERNAL_IN_UPDATE_ELAPSED_TIME", - [BGP_INTERNAL_END] = "BGP_INTERNAL_END", - [BGP_INTERNAL_NO_VALUE] = "BGP_INTERNAL_NO_VALUE", + [BGP_INTERNAL_IN_UPDATE_ELAPSED_TIME] = "BGP_INTERNAL_IN_UPDATE_ELAPSED_TIME", + [BGP_INTERNAL_END] = "BGP_INTERNAL_END", + [BGP_INTERNAL_NO_VALUE] = "BGP_INTERNAL_NO_VALUE", }; void @@ -222,7 +222,7 @@ print_bgp_record(struct bgp_config *config) struct bgp_conn *conn = bgp_proto->conn; snmp_log(" name: %s", cf->name); - snmp_log(""); + snmp_log("."); snmp_log(" rem. identifier: %u", bgp_proto->remote_id); snmp_log(" local ip: %I", config->local_ip); snmp_log(" remote ip: %I", config->remote_ip); @@ -280,11 +280,11 @@ print_bgp_record_all(struct snmp_proto *p) * * Returns linearized state for Get-PDU, GetNext-PDU and GetBulk-PDU packets. */ -u8 -snmp_bgp_state(struct oid *oid) +static u8 +snmp_bgp_state(const struct oid *oid) { /* already checked: - xxxxxxxx p + * xxxxxxxx p * (*oid): .1.3.6.1.2.1.15 * -> BGP4-MIB::bgp (root) */ @@ -352,7 +352,6 @@ snmp_bgp_state(struct oid *oid) state = BGP_INTERNAL_NO_VALUE; candidate = BGP_INTERNAL_NO_VALUE; } - else /* oid->ids[2] > SNMP_BGP_PEER_TABLE */ state = BGP_INTERNAL_END; } @@ -446,7 +445,7 @@ snmp_bgp_is_supported(struct oid *o) o->ids[1] == BGP4_MIB_LOCAL_AS)) return 1; else if (o->n_subid > 2 && o->ids[1] == BGP4_PEER_TABLE && - o->ids[2] == BGP4_PEER_ENTRY) + o->ids[2] == BGP4_PEER_ENTRY) { if (o->n_subid == 3) return 1; @@ -724,7 +723,8 @@ UNUSED, u8 current_state) /* TODO can be remove after implementing all BGP4-MIB::bgpPeerTable columns */ u8 next_state = current_state; struct oid *o_copy = o_start; - do { + do + { snmp_log("do-while state %u", next_state); snmp_oid_dump(o_start); o_start = o_copy = update_bgp_oid(o_copy, next_state); @@ -996,7 +996,7 @@ snmp_bgp_search(struct snmp_proto *p, struct oid *o_start, struct oid *o_end, ui // o_start = update_bgp_oid(o_start, next_state); // snmp_oid_dump(o_start); // -// snmp_log("search_bgp_mib() is NOT next_state dynamic %s", +// snmp_log("snmp_bgp_search() is NOT next_state dynamic %s", // !is_dynamic(next_state) ? "true" : "false"); // // if (!is_dynamic(next_state)) diff --git a/proto/snmp/bgp_mib.h b/proto/snmp/bgp_mib.h index e27f1d51..43c927e3 100644 --- a/proto/snmp/bgp_mib.h +++ b/proto/snmp/bgp_mib.h @@ -45,7 +45,7 @@ void snmp_bgp_register(struct snmp_proto *p); // - int snmp_bgp_is_supported(struct oid *o); //int snmp_bgp_valid_ip4(struct oid *o); -u8 snmp_bgp_state(struct oid *o); +//u8 snmp_bgp_state(const struct oid *o); u8 snmp_bgp_get_valid(u8 state); u8 snmp_bgp_getnext_valid(u8 state); diff --git a/proto/snmp/snmp.c b/proto/snmp/snmp.c index e5d1b66d..d958722a 100644 --- a/proto/snmp/snmp.c +++ b/proto/snmp/snmp.c @@ -15,6 +15,7 @@ #include "snmp.h" #include "subagent.h" +#include "snmp_utils.h" static void snmp_connected(sock *sk); static void snmp_sock_err(sock *sk, int err); @@ -22,7 +23,7 @@ static void snmp_ping_timer(struct timer *tm); static void snmp_startup(struct snmp_proto *p); static void snmp_startup_timeout(timer *t); static void snmp_start_locked(struct object_lock *lock); - +static int snmp_shutdown(struct proto *P); static const char * const snmp_state[] = { [SNMP_ERR] = "SNMP ERROR", @@ -49,7 +50,7 @@ snmp_init(struct proto_config *CF) p->local_port = cf->local_port; p->remote_port = cf->remote_port; p->local_as = cf->local_as; - snmp_log("chaning proto_snmp state to INIT"); + snmp_log("changing proto_snmp state to INIT"); p->state = SNMP_INIT; // p->timeout = cf->timeout; @@ -64,14 +65,25 @@ 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); if (p->sock != NULL) rfree(p->sock); + p->sock = NULL; if (p->lock != NULL) rfree(p->lock); + p->lock = NULL; p->state = SNMP_DOWN; } @@ -177,18 +189,14 @@ snmp_start_locked(struct object_lock *lock) snmp_log("socket ready!, trying to connect"); } -static void -snmp_tx(sock *sk UNUSED) -{ - snmp_log("snmp_tx() something, yay!"); -} - static void snmp_connected(sock *sk) { struct snmp_proto *p = sk->data; snmp_log("snmp_connected() connection created"); - byte *buf UNUSED = sk->rbuf; + 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; @@ -203,8 +211,9 @@ static void snmp_sock_err(sock *sk, int err) { snmp_log("snmp_sock_err() %s - err no: %d", strerror(err), err); - struct snmp_proto *p = sk->data; + p->errs++; + tm_stop(p->ping_timer); rfree(p->sock); @@ -214,10 +223,16 @@ snmp_sock_err(sock *sk, int err) p->lock = NULL; snmp_log("changing proto_snmp state to ERR[OR]"); - p->state = SNMP_ERR; + if (err) + p->state = SNMP_ERR; + else + { + snmp_shutdown((struct proto *) p); + return; + } // TODO ping interval - tm_start(p->startup_timer, 15 S); + tm_start(p->startup_timer, 4 S); } static int @@ -274,15 +289,17 @@ snmp_start(struct proto *P) peer->config = (struct bgp_config *) b->proto; peer->peer_ip = bc->remote_ip; - struct net_addr *net = mb_allocz(p->p.pool, sizeof(struct net_addr)); - net_fill_ip4(net, ipa_to_ip4(peer->peer_ip), IP4_MAX_PREFIX_LENGTH); + struct net_addr net; + net_fill_ip4(&net, ipa_to_ip4(peer->peer_ip), IP4_MAX_PREFIX_LENGTH); - trie_add_prefix(p->bgp_trie, net, IP4_MAX_PREFIX_LENGTH, IP4_MAX_PREFIX_LENGTH); + trie_add_prefix(p->bgp_trie, &net, IP4_MAX_PREFIX_LENGTH, IP4_MAX_PREFIX_LENGTH); HASH_INSERT(p->bgp_hash, SNMP_HASH, peer); } } + init_list(&p->additional_buffers); + snmp_startup(p); return PS_START; } @@ -311,7 +328,8 @@ snmp_reconfigure(struct proto *P, struct proto_config *CF) return 1; } -static void snmp_show_proto_info(struct proto *P) +static void +snmp_show_proto_info(struct proto *P) { struct snmp_proto *sp = (void *) P; struct snmp_config *c = (void *) P->cf; @@ -384,6 +402,7 @@ bp->stats.fsm_established_transitions); static void snmp_postconfig(struct proto_config *CF) { + // walk the bgp protocols and cache their references if (((struct snmp_config *) CF)->local_as == 0) cf_error("local as not specified"); } diff --git a/proto/snmp/snmp.h b/proto/snmp/snmp.h index acf1db20..21d777d2 100644 --- a/proto/snmp/snmp.h +++ b/proto/snmp/snmp.h @@ -113,8 +113,7 @@ struct snmp_proto { uint register_to_ack; /* counter of pending responses to register-pdu */ list register_queue; /* list containing snmp_register records */ list bgp_registered; /* list of currently registered bgp oids - (struct snmp_registered_oid) */ - //struct iface *iface; + * (struct snmp_registered_oid) */ // map struct f_trie *bgp_trie; @@ -129,16 +128,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 */ }; -/* -struct snmp_pdu { - node n; - - //u32 session_id; - u32 transaction_id; - u32 packet_id; // in future need support for ranges of packet_id-s -}; -*/ +void snmp_tx(sock *sk); #endif diff --git a/proto/snmp/snmp_utils.c b/proto/snmp/snmp_utils.c index 853697d5..b6421cb3 100644 --- a/proto/snmp/snmp_utils.c +++ b/proto/snmp/snmp_utils.c @@ -184,7 +184,7 @@ snmp_valid_ip4_index(const struct oid *o, uint start) if (start + 3 < o->n_subid) return snmp_valid_ip4_index_unsafe(o, start); else - return 0; // false + return 0; } /** @@ -200,9 +200,9 @@ snmp_valid_ip4_index_unsafe(const struct oid *o, uint start) { for (int i = 0; i < 4; i++) if (o->ids[start + i] >= 256) - return 0; // false + return 0; - return 1; // true + return 1; } byte * @@ -267,7 +267,7 @@ snmp_put_oid(byte *buf, struct oid *oid) put_u8(buf, oid->n_subid); put_u8(++buf, oid->prefix); put_u8(++buf, oid->include); - put_u8(++buf, 0); // PADDING + put_u8(++buf, 0); // padding /* last increment */ ++buf; @@ -357,16 +357,6 @@ snmp_oid_compare(const struct oid *left, const struct oid *right) { const u32 INTERNET_PREFIX[] = {1, 3, 6, 1}; - /* - if (snmp_is_oid_empty(left) && snmp_is_oid_empty(right)) - return 0; - - if (snmp_is_oid_empty(right)) - return -1; - - if (snmp_is_oid_empty(left)) - return 1; - */ if (left->prefix == 0 && right->prefix == 0) goto test_ids; diff --git a/proto/snmp/subagent.c b/proto/snmp/subagent.c index cde603ba..bd31a5cd 100644 --- a/proto/snmp/subagent.c +++ b/proto/snmp/subagent.c @@ -221,6 +221,7 @@ de_allocate_pdu(struct snmp_proto *p, struct oid *oid, u8 type) buf = pkt = sk->tbuf; uint size = sk->tbsize; + if (size > AGENTX_HEADER_SIZE + ) { snmp_log("de_allocate_pdu()"); @@ -447,21 +448,34 @@ removeagentcaps_pdu(struct snmp_proto *p, struct oid *cap, struct agentx_context return; } - snmp_log("preparing to sk_send()"); - int ret = sk_send(sk, pkt - buf); struct agentx_header *h; SNMP_CREATE(buf, struct agentx_header, h); SNMP_SESSION(h, p); ADVANCE(buf, size, AGENTX_HEADER_SIZE); - if (ret == 0) - snmp_log("sk_send sleep"); - else if (ret < 0) - snmp_log("sk_send err"); - else - log(L_INFO, "sk_send ok !!"); + uint in_pkt; + if (c && c->length) + { + SNMP_HAS_CONTEXT(h); + in_pkt = snmp_put_nstr(buf, c->context, c->length) - buf; + ADVANCE(buf, size, in_pkt); } + + memcpy(buf, cap, snmp_oid_size(cap)); + ADVANCE(buf, size, snmp_oid_size(cap)); + + // update state in snmp_proto structure + + //int ret = sk_send(sk, buf - sk->tbuf); + 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 static inline void refresh_ids(struct snmp_proto *p, struct agentx_header *h) @@ -594,7 +608,8 @@ snmp_registered_all(struct snmp_proto *p) } static void -snmp_register_mibs(struct snmp_proto *p) { +snmp_register_mibs(struct snmp_proto *p) +{ snmp_log("snmp_register_mibs()"); snmp_bgp_register(p);