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.
|
|
|
|
*/
|
|
|
|
|
2023-09-04 07:25:51 +00:00
|
|
|
/**
|
|
|
|
* Simple Network Management Protocol State Machine
|
|
|
|
*
|
|
|
|
* States with main transitions
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* +-----------------+
|
|
|
|
* | SNMP_INIT | entry state after call snmp_start()
|
|
|
|
* +-----------------+
|
|
|
|
* |
|
|
|
|
* | acquiring object lock for communication socket
|
|
|
|
* V
|
|
|
|
* +-----------------+
|
|
|
|
* | SNMP_LOCKED | object lock aquired
|
|
|
|
* +-----------------+
|
|
|
|
* |
|
|
|
|
* | opening communaiton socket
|
|
|
|
* V
|
|
|
|
* +-----------------+
|
|
|
|
* | SNMP_OPEN | socket created, starting subagent
|
|
|
|
* +-----------------+
|
|
|
|
* |
|
|
|
|
* | BIRD recieve response for Open-PDU
|
|
|
|
* V
|
|
|
|
* +-----------------+
|
|
|
|
* | SNMP_REGISTER | session was established, subagent registers MIBs
|
|
|
|
* +-----------------+
|
|
|
|
* |
|
|
|
|
* | subagent recieved responses for all registration requests
|
|
|
|
* V
|
|
|
|
* +-----------------+
|
|
|
|
* | SNMP_CONN | everything is set
|
|
|
|
* +-----------------+
|
|
|
|
* |
|
|
|
|
* | function snmp_shutdown() is called, BIRD sends Close-PDU
|
|
|
|
* V
|
|
|
|
* +-----------------+
|
|
|
|
* | SNMP_STOP | waiting for response
|
|
|
|
* +-----------------+
|
|
|
|
* |
|
|
|
|
* | cleaning old state information
|
|
|
|
* V
|
|
|
|
* +-----------------+
|
|
|
|
* | SNMP_DOWN | session is closed
|
|
|
|
* +-----------------+
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* Erroneous transitions:
|
|
|
|
* SNMP is UP in states SNMP_CONN and also in SNMP_REGISTER because the
|
|
|
|
* session is establised and the GetNext request should be responsed
|
|
|
|
* without regard to MIB registration.
|
|
|
|
*
|
|
|
|
* When the session has been closed for some reason (socket error, reciept of
|
|
|
|
* Close-PDU) SNMP cleans the session information and message queue and goes
|
|
|
|
* back to the SNMP_LOCKED state.
|
|
|
|
*
|
|
|
|
* Reconfiguration is done in similar fashion to BGP, the reconfiguration
|
|
|
|
* request is declined, the protocols is stoped and started with new
|
|
|
|
* configuration.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
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"
|
2023-07-26 12:34:01 +00:00
|
|
|
#include "snmp_utils.h"
|
2022-08-10 15:31:32 +00:00
|
|
|
|
2022-11-29 15:30:20 +00:00
|
|
|
static const char * const snmp_state[] = {
|
2023-09-04 07:25:51 +00:00
|
|
|
[SNMP_INIT] = "SNMP INIT",
|
|
|
|
[SNMP_LOCKED] = "SNMP LOCKED",
|
|
|
|
[SNMP_OPEN] = "SNMP CONNECTION OPENED",
|
|
|
|
[SNMP_REGISTER] = "SNMP REGISTERING MIBS",
|
|
|
|
[SNMP_CONN] = "SNMP CONNECTED",
|
2023-09-04 11:48:28 +00:00
|
|
|
[SNMP_STOP] = "SNMP STOPPING",
|
2023-09-04 07:25:51 +00:00
|
|
|
[SNMP_DOWN] = "SNMP DOWN",
|
2022-11-29 15:30:20 +00:00
|
|
|
};
|
|
|
|
|
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);
|
2022-12-10 12:23:50 +00:00
|
|
|
const 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;
|
2023-10-11 08:44:18 +00:00
|
|
|
|
|
|
|
p->bgp_local_as = cf->bgp_local_as;
|
|
|
|
p->bgp_local_id = cf->bgp_local_id;
|
|
|
|
|
2023-10-18 16:06:24 +00:00
|
|
|
snmp_log("changing state to INIT");
|
2022-09-06 16:04:29 +00:00
|
|
|
p->state = SNMP_INIT;
|
2022-08-10 15:31:32 +00:00
|
|
|
|
2023-09-04 11:58:59 +00:00
|
|
|
p->timeout = cf->timeout;
|
2022-08-10 15:31:32 +00:00
|
|
|
|
2023-09-11 11:06:20 +00:00
|
|
|
/* used when assigning the context ids in s_cont_create() */
|
|
|
|
p->context_max = 1;
|
|
|
|
p->context_id_map = NULL;
|
|
|
|
|
2022-08-01 11:01:49 +00:00
|
|
|
return P;
|
|
|
|
}
|
|
|
|
|
2023-09-04 11:58:59 +00:00
|
|
|
static inline int
|
2022-12-17 17:16:19 +00:00
|
|
|
snmp_cleanup(struct snmp_proto *p)
|
2022-12-10 12:23:50 +00:00
|
|
|
{
|
2023-09-04 11:58:59 +00:00
|
|
|
/* Function tm_stop() is called inside rfree() */
|
2022-12-17 17:16:19 +00:00
|
|
|
rfree(p->startup_timer);
|
2023-08-08 17:00:54 +00:00
|
|
|
p->startup_timer = NULL;
|
|
|
|
|
2022-12-17 17:16:19 +00:00
|
|
|
rfree(p->ping_timer);
|
2023-08-08 17:00:54 +00:00
|
|
|
p->ping_timer = NULL;
|
2022-12-17 17:16:19 +00:00
|
|
|
|
2023-08-08 17:00:54 +00:00
|
|
|
rfree(p->sock);
|
2023-07-26 12:34:01 +00:00
|
|
|
p->sock = NULL;
|
2022-12-10 12:23:50 +00:00
|
|
|
|
2023-08-08 17:00:54 +00:00
|
|
|
rfree(p->lock);
|
2023-07-26 12:34:01 +00:00
|
|
|
p->lock = NULL;
|
2022-12-10 12:23:50 +00:00
|
|
|
|
2023-09-11 11:06:20 +00:00
|
|
|
struct snmp_register *r, *r2;
|
|
|
|
WALK_LIST_DELSAFE(r, r2, p->register_queue)
|
|
|
|
{
|
|
|
|
rem_node(&r->n);
|
|
|
|
mb_free(r);
|
|
|
|
r = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct snmp_registered_oid *ro, *ro2;
|
|
|
|
WALK_LIST_DELSAFE(ro, ro2, p->bgp_registered)
|
|
|
|
{
|
|
|
|
rem_node(&r->n);
|
|
|
|
mb_free(ro);
|
|
|
|
ro = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
HASH_FREE(p->bgp_hash);
|
|
|
|
HASH_FREE(p->context_hash);
|
|
|
|
mb_free(p->context_id_map);
|
|
|
|
p->context_id_map = NULL;
|
|
|
|
|
2023-10-18 14:51:21 +00:00
|
|
|
rfree(p->lp);
|
|
|
|
p->bgp_trie = NULL;
|
2023-09-04 11:58:59 +00:00
|
|
|
|
2023-10-18 14:51:21 +00:00
|
|
|
p->state = SNMP_DOWN;
|
|
|
|
return PS_DOWN;
|
2022-12-17 17:16:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
snmp_down(struct snmp_proto *p)
|
|
|
|
{
|
|
|
|
snmp_cleanup(p);
|
2022-12-10 12:23:50 +00:00
|
|
|
proto_notify_state(&p->p, PS_DOWN);
|
|
|
|
}
|
|
|
|
|
2023-10-18 11:30:14 +00:00
|
|
|
/* this function is internal and shouldn't be used outside the snmp module */
|
|
|
|
void
|
|
|
|
snmp_connected(sock *sk)
|
|
|
|
{
|
|
|
|
struct snmp_proto *p = sk->data;
|
2023-10-18 16:06:24 +00:00
|
|
|
snmp_log("connection created");
|
2023-10-18 11:30:14 +00:00
|
|
|
|
|
|
|
p->state = SNMP_OPEN;
|
|
|
|
|
|
|
|
sk->rx_hook = snmp_rx;
|
|
|
|
sk->tx_hook = NULL;
|
|
|
|
//sk->tx_hook = snmp_tx;
|
|
|
|
|
|
|
|
snmp_start_subagent(p);
|
|
|
|
|
|
|
|
// TODO ping interval <move to do_response()>
|
|
|
|
tm_set(p->ping_timer, current_time() + p->timeout S);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* this function is internal and shouldn't be used outside the snmp module */
|
|
|
|
void
|
|
|
|
snmp_reconnect(timer *tm)
|
|
|
|
{
|
|
|
|
struct snmp_proto *p = tm->data;
|
|
|
|
ASSUME(p->sock);
|
|
|
|
snmp_connected(p->sock);
|
|
|
|
}
|
|
|
|
|
2022-09-30 07:36:09 +00:00
|
|
|
static void
|
2023-10-18 16:06:24 +00:00
|
|
|
snmp_sock_err(sock *sk, int UNUSED err)
|
2022-09-30 07:36:09 +00:00
|
|
|
{
|
2023-10-18 16:06:24 +00:00
|
|
|
snmp_log("socket error '%s' (errno: %d)", strerror(err), err);
|
2023-09-04 11:48:28 +00:00
|
|
|
struct snmp_proto *p = sk->data;
|
|
|
|
p->errs++;
|
2022-09-30 07:36:09 +00:00
|
|
|
|
2023-09-04 11:48:28 +00:00
|
|
|
tm_stop(p->ping_timer);
|
2022-12-17 17:16:19 +00:00
|
|
|
|
2023-09-04 12:01:08 +00:00
|
|
|
proto_notify_state(&p->p, PS_START);
|
2023-09-04 11:48:28 +00:00
|
|
|
rfree(p->sock);
|
|
|
|
p->sock = NULL;
|
2022-12-17 17:16:19 +00:00
|
|
|
|
2023-10-18 16:06:24 +00:00
|
|
|
snmp_log("changing state to LOCKED");
|
2023-09-04 11:58:59 +00:00
|
|
|
p->state = SNMP_LOCKED;
|
2023-09-04 11:48:28 +00:00
|
|
|
|
2023-10-18 11:30:14 +00:00
|
|
|
p->startup_timer->hook = snmp_startup_timeout;
|
|
|
|
tm_start(p->startup_timer, 4 S); // TODO make me configurable
|
2022-12-17 17:16:19 +00:00
|
|
|
}
|
|
|
|
|
2022-09-30 07:36:09 +00:00
|
|
|
|
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
|
|
|
{
|
2023-10-18 16:06:24 +00:00
|
|
|
//snmp_log("snmp_start_locked() - lock acquired; preparing socket");
|
2022-08-10 15:31:32 +00:00
|
|
|
struct snmp_proto *p = lock->data;
|
|
|
|
|
2023-09-04 07:25:51 +00:00
|
|
|
p->state = SNMP_LOCKED;
|
2023-10-18 11:30:14 +00:00
|
|
|
sock *s = p->sock;
|
2023-09-04 07:25:51 +00:00
|
|
|
|
2023-10-18 14:51:21 +00:00
|
|
|
if (!p->bgp_trie)
|
|
|
|
p->bgp_trie = f_new_trie(p->lp, 0); // TODO user-data attachment size
|
|
|
|
|
2023-10-18 11:30:14 +00:00
|
|
|
if (!s)
|
|
|
|
{
|
2023-10-18 14:51:21 +00:00
|
|
|
s = sk_new(p->pool);
|
2023-10-18 11:30:14 +00:00
|
|
|
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;
|
|
|
|
|
|
|
|
//s->tos = IP_PREC_INTERNET_CONTROL
|
|
|
|
s->tx_hook = snmp_connected;
|
|
|
|
s->err_hook = snmp_sock_err;
|
|
|
|
|
|
|
|
p->sock = s;
|
|
|
|
s->data = p;
|
|
|
|
|
|
|
|
p->to_send = 0;
|
|
|
|
p->errs = 0;
|
|
|
|
}
|
2022-09-30 07:36:09 +00:00
|
|
|
|
2023-10-18 16:06:24 +00:00
|
|
|
snmp_log("opening socket");
|
2023-10-19 14:20:37 +00:00
|
|
|
/* Try opening the socket, schedule a retry on fail */
|
2022-09-30 07:36:09 +00:00
|
|
|
if (sk_open(s) < 0)
|
2023-10-19 14:20:37 +00:00
|
|
|
tm_set(p->startup_timer, current_time() + p->timeout S);
|
2022-08-10 15:31:32 +00:00
|
|
|
}
|
|
|
|
|
2023-10-18 11:30:14 +00:00
|
|
|
/* this function is internal and shouldn't be used outside the snmp module */
|
|
|
|
void
|
2023-09-04 11:48:28 +00:00
|
|
|
snmp_startup(struct snmp_proto *p)
|
2022-08-10 15:31:32 +00:00
|
|
|
{
|
2023-09-04 11:58:59 +00:00
|
|
|
if (p->state != SNMP_INIT &&
|
|
|
|
p->state != SNMP_LOCKED &&
|
|
|
|
p->state != SNMP_DOWN)
|
2023-09-04 11:48:28 +00:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2023-09-04 07:25:51 +00:00
|
|
|
|
2023-09-04 11:58:59 +00:00
|
|
|
if (p->lock)
|
|
|
|
{
|
|
|
|
snmp_start_locked(p->lock);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-10-18 16:06:24 +00:00
|
|
|
snmp_log("preparing object lock");
|
2023-09-04 11:48:28 +00:00
|
|
|
p->state = SNMP_INIT;
|
2022-08-10 15:31:32 +00:00
|
|
|
|
2023-09-04 11:48:28 +00:00
|
|
|
struct object_lock *lock;
|
2023-10-18 14:51:21 +00:00
|
|
|
lock = p->lock = olock_new(p->pool);
|
2023-09-04 11:48:28 +00:00
|
|
|
|
|
|
|
// lock->addr
|
|
|
|
// lock->port
|
|
|
|
// lock->iface
|
|
|
|
// lock->vrf
|
|
|
|
lock->type = OBJLOCK_TCP;
|
|
|
|
lock->hook = snmp_start_locked;
|
|
|
|
lock->data = p;
|
|
|
|
|
|
|
|
olock_acquire(lock);
|
2022-08-10 15:31:32 +00:00
|
|
|
}
|
2022-08-02 14:04:25 +00:00
|
|
|
|
2023-10-18 11:30:14 +00:00
|
|
|
/* this function is internal and shouldn't be used outside the snmp module */
|
|
|
|
void
|
2023-09-04 11:48:28 +00:00
|
|
|
snmp_startup_timeout(timer *t)
|
2022-08-10 15:31:32 +00:00
|
|
|
{
|
2023-09-04 11:48:28 +00:00
|
|
|
snmp_log("startup timer triggered");
|
|
|
|
snmp_startup(t->data);
|
|
|
|
}
|
2023-07-26 12:34:01 +00:00
|
|
|
|
2023-09-04 11:48:28 +00:00
|
|
|
static void
|
|
|
|
snmp_stop_timeout(timer *t)
|
|
|
|
{
|
|
|
|
snmp_log("stop timer triggered");
|
2023-10-19 14:20:37 +00:00
|
|
|
snmp_down(t->data);
|
2023-09-04 11:48:28 +00:00
|
|
|
}
|
2022-11-29 15:30:20 +00:00
|
|
|
|
2023-09-04 11:48:28 +00:00
|
|
|
static void
|
2023-10-18 11:30:14 +00:00
|
|
|
snmp_ping_timeout(timer *tm)
|
2023-09-04 11:48:28 +00:00
|
|
|
{
|
|
|
|
struct snmp_proto *p = tm->data;
|
2022-12-17 17:16:19 +00:00
|
|
|
|
2023-09-04 11:58:59 +00:00
|
|
|
if (p->state == SNMP_REGISTER ||
|
|
|
|
p->state == SNMP_CONN)
|
2023-09-04 11:48:28 +00:00
|
|
|
{
|
|
|
|
snmp_ping(p);
|
|
|
|
}
|
|
|
|
|
2023-09-04 11:58:59 +00:00
|
|
|
tm_set(tm, current_time() + p->timeout S);
|
2022-08-02 14:04:25 +00:00
|
|
|
}
|
|
|
|
|
2022-08-01 11:01:49 +00:00
|
|
|
static int
|
|
|
|
snmp_start(struct proto *P)
|
|
|
|
{
|
2023-10-18 16:06:24 +00:00
|
|
|
//snmp_log("snmp_start() - starting timer (almost)");
|
2022-08-10 15:31:32 +00:00
|
|
|
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
|
|
|
|
2022-09-30 07:36:09 +00:00
|
|
|
p->to_send = 0;
|
|
|
|
p->errs = 0;
|
2023-09-04 12:01:08 +00:00
|
|
|
|
2023-10-18 14:51:21 +00:00
|
|
|
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);
|
2022-09-30 07:36:09 +00:00
|
|
|
|
2023-10-18 14:51:21 +00:00
|
|
|
p->pool = p->p.pool;
|
|
|
|
p->lp = lp_new(p->pool);
|
|
|
|
p->bgp_trie = f_new_trie(p->lp, 0);
|
|
|
|
//p->bgp_trie = f_new_trie(lp, cf->bonds); // TODO user-data attachment size
|
2022-09-30 07:36:09 +00:00
|
|
|
|
2022-12-10 17:08:00 +00:00
|
|
|
init_list(&p->register_queue);
|
|
|
|
init_list(&p->bgp_registered);
|
2022-08-10 15:31:32 +00:00
|
|
|
|
2023-09-04 12:01:08 +00:00
|
|
|
/* We create copy of bonds to BGP protocols. */
|
2023-10-18 14:51:21 +00:00
|
|
|
HASH_INIT(p->bgp_hash, p->pool, 10);
|
|
|
|
HASH_INIT(p->context_hash, p->pool, 10);
|
2023-09-11 11:06:20 +00:00
|
|
|
|
|
|
|
/* We always have at least the default context */
|
2023-10-18 14:51:21 +00:00
|
|
|
p->context_id_map = mb_allocz(p->pool, cf->contexts * sizeof(struct snmp_context *));
|
2023-10-18 16:06:24 +00:00
|
|
|
//log(L_INFO "number of context allocated %d", cf->contexts);
|
2023-09-11 11:06:20 +00:00
|
|
|
|
2023-10-18 14:51:21 +00:00
|
|
|
struct snmp_context *defaultc = mb_alloc(p->pool, sizeof(struct snmp_context));
|
2023-09-11 11:06:20 +00:00
|
|
|
defaultc->context = "";
|
|
|
|
defaultc->context_id = 0;
|
|
|
|
defaultc->flags = 0; /* TODO Default context fl. */
|
|
|
|
HASH_INSERT(p->context_hash, SNMP_H_CONTEXT, defaultc);
|
|
|
|
|
|
|
|
p->context_id_map[0] = defaultc;
|
2022-09-06 16:04:29 +00:00
|
|
|
|
2022-09-30 07:36:09 +00:00
|
|
|
struct snmp_bond *b;
|
2022-09-06 16:04:29 +00:00
|
|
|
WALK_LIST(b, cf->bgp_entries)
|
|
|
|
{
|
2023-09-11 11:06:20 +00:00
|
|
|
const struct bgp_config *bc = (struct bgp_config *) b->proto;
|
2022-09-06 16:04:29 +00:00
|
|
|
if (bc && !ipa_zero(bc->remote_ip))
|
|
|
|
{
|
2023-09-04 12:01:08 +00:00
|
|
|
struct snmp_bgp_peer *peer = \
|
2023-10-18 14:51:21 +00:00
|
|
|
mb_allocz(p->pool, sizeof(struct snmp_bgp_peer));
|
2023-09-11 11:06:20 +00:00
|
|
|
peer->config = bc;
|
2022-09-20 12:28:57 +00:00
|
|
|
peer->peer_ip = bc->remote_ip;
|
2022-09-06 16:04:29 +00:00
|
|
|
|
2023-07-26 12:34:01 +00:00
|
|
|
struct net_addr net;
|
|
|
|
net_fill_ip4(&net, ipa_to_ip4(peer->peer_ip), IP4_MAX_PREFIX_LENGTH);
|
2022-09-30 07:36:09 +00:00
|
|
|
|
2023-07-26 12:34:01 +00:00
|
|
|
trie_add_prefix(p->bgp_trie, &net, IP4_MAX_PREFIX_LENGTH, IP4_MAX_PREFIX_LENGTH);
|
2022-09-30 07:36:09 +00:00
|
|
|
|
2022-09-20 12:28:57 +00:00
|
|
|
HASH_INSERT(p->bgp_hash, SNMP_HASH, peer);
|
2023-09-11 11:06:20 +00:00
|
|
|
|
|
|
|
/* Handle non-default context */
|
|
|
|
if (b->context)
|
|
|
|
{
|
|
|
|
const struct snmp_context *c = snmp_cont_create(p, b->context);
|
2023-10-18 16:06:24 +00:00
|
|
|
//snmp_log("creating snmp context %s with id %u, writing", b->context, c->context_id);
|
2023-09-11 11:06:20 +00:00
|
|
|
p->context_id_map[c->context_id] = c;
|
|
|
|
peer->context_id = c->context_id;
|
|
|
|
}
|
2022-09-06 16:04:29 +00:00
|
|
|
}
|
|
|
|
}
|
2022-09-30 07:36:09 +00:00
|
|
|
|
2023-10-18 16:06:24 +00:00
|
|
|
//snmp_log("values of context cf %u proto %u", cf->contexts, p->context_max);
|
2023-09-11 11:06:20 +00:00
|
|
|
ASSUME(cf->contexts == p->context_max);
|
|
|
|
|
2022-12-10 12:23:50 +00:00
|
|
|
snmp_startup(p);
|
2022-09-30 07:36:09 +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);
|
2023-09-04 11:58:59 +00:00
|
|
|
const struct snmp_config *new = SKIP_BACK(struct snmp_config, cf, CF);
|
|
|
|
const struct snmp_config *old = SKIP_BACK(struct snmp_config, cf, p->p.cf);
|
2022-08-10 15:31:32 +00:00
|
|
|
|
2023-09-11 11:06:20 +00:00
|
|
|
struct snmp_bond *b1, *b2;
|
|
|
|
WALK_LIST(b1, new->bgp_entries)
|
|
|
|
{
|
|
|
|
WALK_LIST(b2, old->bgp_entries)
|
|
|
|
{
|
|
|
|
if (!strcmp(b1->proto->name, b2->proto->name))
|
|
|
|
goto skip;
|
|
|
|
|
|
|
|
/* Both bonds use default context */
|
|
|
|
if (!b1->context && !b2->context)
|
|
|
|
goto skip;
|
|
|
|
|
|
|
|
/* Both bonds use same non-default context */
|
|
|
|
if (b1->context && b2->context && !strcmp(b1->context, b2->context))
|
|
|
|
goto skip;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
skip:;
|
|
|
|
}
|
|
|
|
|
2023-09-04 12:01:08 +00:00
|
|
|
return !memcmp(((byte *) old) + sizeof(struct proto_config),
|
2023-09-04 11:58:59 +00:00
|
|
|
((byte *) new) + sizeof(struct proto_config),
|
|
|
|
OFFSETOF(struct snmp_config, description) - sizeof(struct proto_config))
|
|
|
|
&& ! strncmp(old->description, new->description, UINT32_MAX);
|
2022-08-01 11:01:49 +00:00
|
|
|
}
|
2022-09-30 07:36:09 +00:00
|
|
|
|
2023-07-26 12:34:01 +00:00
|
|
|
static void
|
|
|
|
snmp_show_proto_info(struct proto *P)
|
2022-08-01 11:01:49 +00:00
|
|
|
{
|
2022-11-29 15:30:20 +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-11-29 15:30:20 +00:00
|
|
|
cli_msg(-1006, "");
|
|
|
|
cli_msg(-1006, " snmp status %s", snmp_state[sp->state]);
|
2023-10-11 08:44:18 +00:00
|
|
|
cli_msg(-1006, " default local as %u", sp->bgp_local_as);
|
|
|
|
cli_msg(-1006, " default local id %I4", sp->bgp_local_id);
|
2022-11-29 15:30:20 +00:00
|
|
|
cli_msg(-1006, "");
|
2022-08-02 14:04:25 +00:00
|
|
|
cli_msg(-1006, " BGP peers");
|
2023-10-11 08:44:18 +00:00
|
|
|
|
2022-08-02 14:04:25 +00:00
|
|
|
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, "");
|
2023-08-08 17:45:50 +00:00
|
|
|
cli_msg(-1006, " loc. identifier: %I4", bp->local_id);
|
|
|
|
cli_msg(-1006, " rem. identifier: %I4", bp->remote_id);
|
2022-12-06 15:32:26 +00:00
|
|
|
cli_msg(-1006, " admin status: %s", (p->disabled) ? "stop" :
|
|
|
|
"start");
|
2022-09-20 12:28:57 +00:00
|
|
|
cli_msg(-1006, " version: 4");
|
2023-08-08 17:45:50 +00:00
|
|
|
cli_msg(-1006, " local ip: %I4", bcf->local_ip);
|
|
|
|
cli_msg(-1006, " remote ip: %I4", bcf->remote_ip);
|
|
|
|
cli_msg(-1006, " local port: %I4", bcf->local_port);
|
|
|
|
cli_msg(-1006, " remote port: %I4", bcf->remote_port);
|
2023-10-18 16:06:24 +00:00
|
|
|
|
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
|
|
|
*/
|
2023-10-18 16:06:24 +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",
|
2023-09-11 11:06:20 +00:00
|
|
|
bp->stats.fsm_established_transitions);
|
2022-08-02 14:04:25 +00:00
|
|
|
|
2023-08-08 17:45:50 +00:00
|
|
|
cli_msg(-1006, " fsm total time: -- (0)");
|
2022-08-02 14:04:25 +00:00
|
|
|
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 );
|
|
|
|
|
2023-08-08 17:45:50 +00:00
|
|
|
cli_msg(-1006, " min AS origin. int.: -- (0)");
|
2022-08-02 14:04:25 +00:00
|
|
|
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);
|
2023-09-04 11:58:59 +00:00
|
|
|
cli_msg(-1006, "");
|
2022-08-01 11:01:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-20 12:28:57 +00:00
|
|
|
static void
|
|
|
|
snmp_postconfig(struct proto_config *CF)
|
|
|
|
{
|
2023-09-04 12:01:08 +00:00
|
|
|
/* Walk the BGP protocols and cache their references. */
|
2023-10-11 08:44:18 +00:00
|
|
|
if (((struct snmp_config *) CF)->bgp_local_as == 0)
|
2022-09-20 12:28:57 +00:00
|
|
|
cf_error("local as not specified");
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
|
|
|
tm_stop(p->ping_timer);
|
|
|
|
|
2023-09-04 11:58:59 +00:00
|
|
|
if (p->state == SNMP_OPEN ||
|
|
|
|
p->state == SNMP_REGISTER ||
|
2023-09-04 07:25:51 +00:00
|
|
|
p->state == SNMP_CONN)
|
2022-12-17 17:16:19 +00:00
|
|
|
{
|
2023-09-04 12:01:08 +00:00
|
|
|
/* We have a connection established (at leased send out Open-PDU). */
|
2023-10-18 16:06:24 +00:00
|
|
|
snmp_log("changing state to STOP");
|
2022-12-17 17:16:19 +00:00
|
|
|
p->state = SNMP_STOP;
|
|
|
|
p->startup_timer->hook = snmp_stop_timeout;
|
2023-10-18 11:30:14 +00:00
|
|
|
tm_set(p->startup_timer, current_time() + p->timeout S);
|
2022-12-17 17:16:19 +00:00
|
|
|
snmp_stop_subagent(p);
|
|
|
|
|
|
|
|
return PS_STOP;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2023-09-04 11:58:59 +00:00
|
|
|
/* We did not create a connection, we clean the lock and other stuff. */
|
|
|
|
return snmp_cleanup(p);
|
2022-12-17 17:16:19 +00:00
|
|
|
}
|
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);
|
|
|
|
}
|
2023-09-04 07:25:51 +00:00
|
|
|
|