2022-08-01 11:01:49 +00:00
|
|
|
/*
|
|
|
|
* BIRD -- Simple Network Management Protocol (SNMP)
|
|
|
|
*
|
|
|
|
* (c) 2022 Vojtech Vilimek <vojtech.vilimek@nic.cz>
|
|
|
|
* (c) 2022 CZ.NIC z.s.p.o.
|
|
|
|
*
|
|
|
|
* Can be freely distributed and used under the terms of the GNU GPL.
|
2022-08-02 14:04:25 +00:00
|
|
|
*
|
|
|
|
* Parts of this file were auto-generated using mib2c
|
|
|
|
* using mib2c.create-dataset.conf
|
2022-08-01 11:01:49 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "nest/bird.h"
|
|
|
|
#include "nest/cli.h"
|
2022-08-10 15:31:32 +00:00
|
|
|
#include "nest/locks.h"
|
|
|
|
#include "lib/socket.h"
|
2022-09-20 12:28:57 +00:00
|
|
|
#include "lib/lists.h"
|
2022-08-01 11:01:49 +00:00
|
|
|
|
2022-08-10 15:31:32 +00:00
|
|
|
#include "snmp.h"
|
|
|
|
#include "subagent.h"
|
|
|
|
|
|
|
|
static void snmp_connected(sock *sk);
|
|
|
|
static void snmp_sock_err(sock *sk, int err);
|
|
|
|
static void snmp_ping_timer(struct timer *tm);
|
2022-09-20 12:28:57 +00:00
|
|
|
static void snmp_retry_timer(struct timer *tm);
|
2022-08-01 11:01:49 +00:00
|
|
|
|
|
|
|
static struct proto *
|
|
|
|
snmp_init(struct proto_config *CF)
|
|
|
|
{
|
|
|
|
struct proto *P = proto_new(CF);
|
2022-08-10 15:31:32 +00:00
|
|
|
struct snmp_proto *p = SKIP_BACK(struct snmp_proto, p, P);
|
|
|
|
struct snmp_config *cf = SKIP_BACK(struct snmp_config, cf, CF);
|
2022-08-01 11:01:49 +00:00
|
|
|
|
|
|
|
p->rl_gen = (struct tbf) TBF_DEFAULT_LOG_LIMITS;
|
|
|
|
|
2022-08-10 15:31:32 +00:00
|
|
|
p->local_ip = cf->local_ip;
|
|
|
|
p->remote_ip = cf->remote_ip;
|
|
|
|
p->local_port = cf->local_port;
|
|
|
|
p->remote_port = cf->remote_port;
|
2022-09-06 16:04:29 +00:00
|
|
|
p->state = SNMP_INIT;
|
2022-08-10 15:31:32 +00:00
|
|
|
|
|
|
|
// p->timeout = cf->timeout;
|
|
|
|
p->timeout = 15;
|
|
|
|
|
|
|
|
log(L_INFO "snmp_reconfigure() lip: %I:%u rip: %I:%u",
|
|
|
|
cf->local_ip, cf->local_port, cf->remote_ip, cf->remote_port);
|
|
|
|
|
2022-08-01 11:01:49 +00:00
|
|
|
return P;
|
|
|
|
}
|
|
|
|
|
2022-08-10 15:31:32 +00:00
|
|
|
static void
|
|
|
|
snmp_start_locked(struct object_lock *lock)
|
2022-08-02 14:04:25 +00:00
|
|
|
{
|
2022-08-10 15:31:32 +00:00
|
|
|
log(L_INFO "snmp_start_locked() - preparing socket ");
|
|
|
|
struct snmp_proto *p = lock->data;
|
|
|
|
|
|
|
|
sock *s = sk_new(p->p.pool);
|
|
|
|
s->type = SK_TCP_ACTIVE;
|
|
|
|
s->saddr = p->local_ip;
|
|
|
|
s->daddr = p->remote_ip;
|
|
|
|
s->dport = p->remote_port;
|
|
|
|
s->rbsize = SNMP_RX_BUFFER_SIZE;
|
|
|
|
s->tbsize = SNMP_TX_BUFFER_SIZE;
|
|
|
|
|
2022-09-06 16:04:29 +00:00
|
|
|
//s->tos = IP_PREC_INTERNET_CONTROL
|
2022-08-10 15:31:32 +00:00
|
|
|
//s->rx_hook = snmp_connected;
|
|
|
|
s->tx_hook = snmp_connected;
|
|
|
|
s->err_hook = snmp_sock_err;
|
|
|
|
|
|
|
|
p->sock = s;
|
|
|
|
s->data = p;
|
|
|
|
|
|
|
|
if (sk_open(s) < 0)
|
|
|
|
log(L_ERR "Cannot open listening socket");
|
|
|
|
|
|
|
|
log(L_INFO "socket ready!, trying to connect");
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
snmp_tx(sock *sk UNUSED)
|
|
|
|
{
|
2022-09-06 16:04:29 +00:00
|
|
|
log(L_INFO "snmp_tx() something, yay!");
|
2022-08-10 15:31:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
snmp_connected(sock *sk)
|
|
|
|
{
|
|
|
|
struct snmp_proto *p = sk->data;
|
|
|
|
log(L_INFO "snmp_connected() connection created");
|
|
|
|
byte *buf UNUSED = sk->rbuf;
|
|
|
|
|
|
|
|
sk->rx_hook = snmp_rx;
|
|
|
|
sk->tx_hook = snmp_tx;
|
|
|
|
|
|
|
|
snmp_start_subagent(p);
|
|
|
|
}
|
2022-08-02 14:04:25 +00:00
|
|
|
|
2022-08-10 15:31:32 +00:00
|
|
|
static void
|
|
|
|
snmp_sock_err(sock *sk UNUSED, int err UNUSED)
|
|
|
|
{
|
2022-09-06 16:04:29 +00:00
|
|
|
log(L_INFO "snmp_sock_err() %s - err no: %d", strerror(err), err);
|
2022-09-20 12:28:57 +00:00
|
|
|
|
|
|
|
struct snmp_proto *p = sk->data;
|
|
|
|
|
|
|
|
p->state = SNMP_ERR;
|
|
|
|
if (p->p.proto_state == PS_UP)
|
|
|
|
proto_notify_state(&p->p, PS_START);
|
|
|
|
|
|
|
|
tm_set(p->retry_timer, current_time() + 5 S);
|
2022-08-02 14:04:25 +00:00
|
|
|
}
|
|
|
|
|
2022-08-01 11:01:49 +00:00
|
|
|
static int
|
|
|
|
snmp_start(struct proto *P)
|
|
|
|
{
|
2022-08-10 15:31:32 +00:00
|
|
|
log(L_INFO "snmp_start() - starting timer (almost)");
|
|
|
|
struct snmp_proto *p = (void *) P;
|
2022-09-20 12:28:57 +00:00
|
|
|
struct snmp_config *cf = (struct snmp_config *) P->cf;
|
2022-08-10 15:31:32 +00:00
|
|
|
|
|
|
|
p->ping_timer = tm_new_init(p->p.pool, snmp_ping_timer, p, 0, 0);
|
2022-09-20 12:28:57 +00:00
|
|
|
tm_set(p->ping_timer, current_time() + 2 S);
|
|
|
|
|
|
|
|
p->retry_timer = tm_new_init(p->p.pool, snmp_retry_timer, p, 0, 0);
|
2022-08-10 15:31:32 +00:00
|
|
|
|
|
|
|
/* starting agentX communicaiton channel */
|
|
|
|
log(L_INFO "preparing lock");
|
|
|
|
struct object_lock *lock;
|
2022-09-20 12:28:57 +00:00
|
|
|
lock = p->lock = olock_new(p->p.pool);
|
2022-08-10 15:31:32 +00:00
|
|
|
|
|
|
|
lock->type = OBJLOCK_TCP;
|
|
|
|
lock->hook = snmp_start_locked;
|
|
|
|
lock->data = p;
|
|
|
|
|
|
|
|
olock_acquire(lock);
|
|
|
|
log(L_INFO "lock acquired");
|
|
|
|
|
|
|
|
log(L_INFO "local ip: %I:%u, remote ip: %I:%u",
|
|
|
|
p->local_ip, p->local_port, p->remote_ip, p->remote_port);
|
2022-09-06 16:04:29 +00:00
|
|
|
|
2022-09-20 12:28:57 +00:00
|
|
|
init_list(&p->bgp_entries);
|
2022-09-06 16:04:29 +00:00
|
|
|
|
|
|
|
/* create copy of bonds to bgp */
|
2022-09-20 12:28:57 +00:00
|
|
|
HASH_INIT(p->bgp_hash, p->p.pool, 10);
|
2022-09-06 16:04:29 +00:00
|
|
|
|
2022-09-20 12:28:57 +00:00
|
|
|
struct snmp_bond *b, *b2;
|
2022-09-06 16:04:29 +00:00
|
|
|
WALK_LIST(b, cf->bgp_entries)
|
|
|
|
{
|
2022-09-20 12:28:57 +00:00
|
|
|
struct bgp_config *bc = (struct bgp_config *) b->proto;
|
2022-09-06 16:04:29 +00:00
|
|
|
if (bc && !ipa_zero(bc->remote_ip))
|
|
|
|
{
|
2022-09-20 12:28:57 +00:00
|
|
|
struct snmp_bgp_peer *peer =
|
|
|
|
mb_allocz(p->p.pool, sizeof(struct snmp_bgp_peer));
|
|
|
|
peer->bond = b;
|
|
|
|
peer->peer_ip = bc->remote_ip;
|
2022-09-06 16:04:29 +00:00
|
|
|
|
2022-09-20 12:28:57 +00:00
|
|
|
HASH_INSERT(p->bgp_hash, SNMP_HASH, peer);
|
2022-09-06 16:04:29 +00:00
|
|
|
|
2022-09-20 12:28:57 +00:00
|
|
|
b2 = mb_allocz(p->p.pool, sizeof(struct snmp_bond));
|
|
|
|
b2->proto = b->proto;
|
|
|
|
b2->type = b->type;
|
|
|
|
add_tail(&p->bgp_entries, NODE b2);
|
|
|
|
mb_free(peer);
|
2022-09-06 16:04:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-08-10 15:31:32 +00:00
|
|
|
return PS_START;
|
2022-08-01 11:01:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
snmp_reconfigure(struct proto *P, struct proto_config *CF)
|
|
|
|
{
|
2022-08-10 15:31:32 +00:00
|
|
|
struct snmp_proto *p = SKIP_BACK(struct snmp_proto, p, P);
|
|
|
|
struct snmp_config *cf = SKIP_BACK(struct snmp_config, cf, CF);
|
|
|
|
|
|
|
|
p->local_ip = cf->local_ip;
|
|
|
|
p->remote_ip = cf->remote_ip;
|
|
|
|
p->local_port = cf->local_port;
|
|
|
|
p->remote_port = cf->remote_port;
|
2022-09-20 12:28:57 +00:00
|
|
|
p->local_as = cf->local_as;
|
2022-08-10 15:31:32 +00:00
|
|
|
p->timeout = 15;
|
|
|
|
|
2022-09-06 16:04:29 +00:00
|
|
|
/* TODO walk all bind protocols and find their (new) IP
|
|
|
|
to update HASH table */
|
2022-08-10 15:31:32 +00:00
|
|
|
log(L_INFO "snmp_reconfigure() lip: %I:%u rip: %I:%u",
|
|
|
|
p->local_ip, p->local_port, p->remote_ip, p->remote_port);
|
2022-09-06 16:04:29 +00:00
|
|
|
return PS_START;
|
2022-08-01 11:01:49 +00:00
|
|
|
}
|
2022-09-06 16:04:29 +00:00
|
|
|
static void snmp_show_proto_info(struct proto *P)
|
2022-08-01 11:01:49 +00:00
|
|
|
{
|
2022-08-10 15:31:32 +00:00
|
|
|
//struct snmp_proto *sp = (void *) P;
|
2022-08-02 14:04:25 +00:00
|
|
|
struct snmp_config *c = (void *) P->cf;
|
2022-08-01 11:01:49 +00:00
|
|
|
|
2022-08-02 14:04:25 +00:00
|
|
|
cli_msg(-1006, " BGP peers");
|
|
|
|
struct snmp_bond *bond;
|
|
|
|
WALK_LIST(bond, c->bgp_entries)
|
2022-08-01 11:01:49 +00:00
|
|
|
{
|
2022-08-02 14:04:25 +00:00
|
|
|
struct proto_config *cf = P->cf;
|
|
|
|
struct bgp_config *bcf = (struct bgp_config *) cf;
|
|
|
|
struct proto *p = cf->proto;
|
|
|
|
struct bgp_proto *bp = (struct bgp_proto *) cf->proto;
|
|
|
|
struct bgp_conn *conn = bp->conn;
|
|
|
|
|
|
|
|
cli_msg(-1006, " name: %s", cf->name);
|
|
|
|
cli_msg(-1006, "");
|
|
|
|
cli_msg(-1006, " rem. identifier: %u", bp->remote_id);
|
|
|
|
// learn more !!
|
|
|
|
cli_msg(-1006, " admin status: %s", (p->disabled) ? "start" :
|
|
|
|
"stop");
|
|
|
|
// version ?
|
2022-09-20 12:28:57 +00:00
|
|
|
cli_msg(-1006, " version: 4");
|
2022-08-02 14:04:25 +00:00
|
|
|
cli_msg(-1006, " local ip: %u", bcf->local_ip);
|
|
|
|
cli_msg(-1006, " remote ip: %u", bcf->remote_ip);
|
|
|
|
cli_msg(-1006, " local port: %u", bcf->local_port);
|
|
|
|
cli_msg(-1006, " remote port: %u", bcf->remote_port);
|
2022-08-10 15:31:32 +00:00
|
|
|
/*
|
2022-08-02 14:04:25 +00:00
|
|
|
if (conn) {
|
|
|
|
cli_msg(-1006, " state: %u", conn->state);
|
|
|
|
cli_msg(-1006, " remote as: %u", conn->remote_caps->as4_number);
|
|
|
|
}
|
2022-08-10 15:31:32 +00:00
|
|
|
*/
|
2022-08-02 14:04:25 +00:00
|
|
|
cli_msg(-1006, " in updates: %u", bp->stats.rx_updates);
|
|
|
|
cli_msg(-1006, " out updates: %u", bp->stats.tx_updates);
|
|
|
|
cli_msg(-1006, " in total: %u", bp->stats.rx_messages);
|
|
|
|
cli_msg(-1006, " out total: %u", bp->stats.tx_messages);
|
|
|
|
cli_msg(-1006, " fsm transitions: %u",
|
|
|
|
bp->stats.fsm_established_transitions);
|
|
|
|
|
|
|
|
// not supported yet
|
|
|
|
cli_msg(-1006, " fsm total time: --");
|
|
|
|
cli_msg(-1006, " retry interval: %u", bcf->connect_retry_time);
|
|
|
|
|
2022-08-10 15:31:32 +00:00
|
|
|
/*
|
2022-08-02 14:04:25 +00:00
|
|
|
if (conn) {
|
|
|
|
cli_msg(-1006, " hold time: %u", conn->hold_time);
|
|
|
|
cli_msg(-1006, " keep alive: %u", conn->keepalive_time );
|
2022-08-01 11:01:49 +00:00
|
|
|
}
|
2022-08-10 15:31:32 +00:00
|
|
|
*/
|
2022-08-02 14:04:25 +00:00
|
|
|
|
|
|
|
cli_msg(-1006, " hold configurated: %u", bcf->hold_time );
|
|
|
|
cli_msg(-1006, " keep alive config: %u", bcf->keepalive_time );
|
|
|
|
|
|
|
|
// unknown
|
|
|
|
cli_msg(-1006, " min AS origin. int.: --");
|
|
|
|
cli_msg(-1006, " min route advertisement: %u", 0 );
|
|
|
|
cli_msg(-1006, " in update elapsed time: %u", 0 );
|
|
|
|
|
|
|
|
if (!conn)
|
|
|
|
cli_msg(-1006, " no default connection");
|
|
|
|
|
|
|
|
cli_msg(-1006, " outgoinin_conn state %u", bp->outgoing_conn.state + 1);
|
|
|
|
cli_msg(-1006, " incoming_conn state: %u", bp->incoming_conn.state + 1);
|
2022-08-01 11:01:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-20 12:28:57 +00:00
|
|
|
static void
|
|
|
|
snmp_postconfig(struct proto_config *CF)
|
|
|
|
{
|
|
|
|
if (((struct snmp_config *) CF)->local_as == 0)
|
|
|
|
cf_error("local as not specified");
|
|
|
|
}
|
|
|
|
|
2022-08-10 15:31:32 +00:00
|
|
|
static void
|
|
|
|
snmp_ping_timer(struct timer *tm)
|
2022-08-01 11:01:49 +00:00
|
|
|
{
|
2022-08-10 15:31:32 +00:00
|
|
|
log(L_INFO "snmp_ping_timer() ");
|
|
|
|
struct snmp_proto *p = tm->data;
|
|
|
|
|
2022-09-20 12:28:57 +00:00
|
|
|
if (p->state == SNMP_CONN)
|
|
|
|
{
|
|
|
|
snmp_ping(p);
|
|
|
|
}
|
2022-09-06 16:04:29 +00:00
|
|
|
|
|
|
|
//tm_set(tm, current_time() + (7 S_));
|
2022-08-01 11:01:49 +00:00
|
|
|
}
|
|
|
|
|
2022-09-20 12:28:57 +00:00
|
|
|
static void
|
|
|
|
snmp_retry_timer(struct timer *tm)
|
|
|
|
{
|
|
|
|
log(L_INFO "snmp_retry_timer()");
|
|
|
|
|
|
|
|
struct snmp_proto *p = tm->data;
|
|
|
|
|
|
|
|
/* starting agentX communicaiton channel */
|
|
|
|
log(L_INFO "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);
|
|
|
|
log(L_INFO "lock acquired");
|
|
|
|
|
|
|
|
log(L_INFO "local ip: %I:%u, remote ip: %I:%u",
|
|
|
|
p->local_ip, p->local_port, p->remote_ip, p->remote_port);
|
|
|
|
}
|
|
|
|
|
2022-08-10 15:31:32 +00:00
|
|
|
static int
|
|
|
|
snmp_shutdown(struct proto *P)
|
2022-08-01 11:01:49 +00:00
|
|
|
{
|
2022-08-10 15:31:32 +00:00
|
|
|
struct snmp_proto *p = SKIP_BACK(struct snmp_proto, p, P);
|
2022-09-20 12:28:57 +00:00
|
|
|
p->state = SNMP_INIT;
|
|
|
|
|
|
|
|
tm_stop(p->ping_timer);
|
|
|
|
tm_stop(p->retry_timer);
|
|
|
|
|
2022-08-10 15:31:32 +00:00
|
|
|
snmp_stop_subagent(p);
|
2022-09-06 16:04:29 +00:00
|
|
|
return PS_DOWN;
|
2022-08-01 11:01:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
struct protocol proto_snmp = {
|
|
|
|
.name = "Snmp",
|
|
|
|
.template = "snmp%d",
|
|
|
|
.channel_mask = NB_ANY,
|
|
|
|
.proto_size = sizeof(struct snmp_proto),
|
|
|
|
.config_size = sizeof(struct snmp_config),
|
2022-09-20 12:28:57 +00:00
|
|
|
.postconfig = snmp_postconfig,
|
2022-08-01 11:01:49 +00:00
|
|
|
.init = snmp_init,
|
|
|
|
.start = snmp_start,
|
|
|
|
.reconfigure = snmp_reconfigure,
|
2022-08-10 15:31:32 +00:00
|
|
|
.shutdown = snmp_shutdown,
|
2022-08-01 11:01:49 +00:00
|
|
|
.show_proto_info = snmp_show_proto_info,
|
|
|
|
};
|
|
|
|
|
|
|
|
void
|
2022-08-10 15:31:32 +00:00
|
|
|
snmp_build(void)
|
2022-08-01 11:01:49 +00:00
|
|
|
{
|
|
|
|
proto_build(&proto_snmp);
|
|
|
|
}
|