0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-12-22 09:41:54 +00:00

SNMP: AgentX over UNIX-domain sockets

This commit is contained in:
Vojtech Vilimek 2024-07-22 18:17:35 +02:00
parent ea643215e2
commit 95438b7608
3 changed files with 86 additions and 27 deletions

View File

@ -31,7 +31,6 @@ snmp_proto:
snmp_proto_item:
proto_item
| snmp_bgp_bond
/* | INTERFACE snmp_interface TODO */
| LOCAL PORT expr {
if (($3 < 1) || ($3 > 65535)) cf_error("Invalid port number");
SNMP_CFG->local_port = $3;
@ -42,12 +41,31 @@ snmp_proto_item:
}
| LOCAL ID IP4 { SNMP_CFG->bgp_local_id = $3; }
| LOCAL ADDRESS IP4 { SNMP_CFG->local_ip = $3; }
| REMOTE ADDRESS DEFAULT {
if (SNMP_CFG->trans_type != SNMP_TRANS_DEFAULT)
cf_error("Duplicit option remote address");
}
| REMOTE ADDRESS IP4 {
if (ip4_zero($3)) cf_error("Invalid remote ip address");
if (SNMP_CFG->trans_type != SNMP_TRANS_DEFAULT)
cf_error("Duplicit option remote address");
// TODO
//if (ip4_zero($3)) cf_error("Invalid remote ip address");
SNMP_CFG->remote_ip = $3;
SNMP_CFG->trans_type = SNMP_TRANS_TCP;
}
| REMOTE ADDRESS text {
if (SNMP_CFG->trans_type != SNMP_TRANS_DEFAULT)
cf_error("Duplicit option remote address");
if (strcmp($3, agentx_master_addr)) {
SNMP_CFG->remote_path = $3;
SNMP_CFG->trans_type = SNMP_TRANS_UNIX;
}
}
| LOCAL AS expr {
if ($3 < 1 || $3 > 65535) cf_error("Invalid local AS");
if ($3 < 1 || $3 > UINT16_MAX) cf_error("Invalid local AS");
SNMP_CFG->bgp_local_as = $3;
}
| SNMP DESCRIPTION text {
@ -87,7 +105,9 @@ snmp_proto_start: proto_start SNMP
SNMP_CFG->bonds = 0;
SNMP_CFG->local_ip = IP4_NONE;
SNMP_CFG->remote_ip = ip4_build(127,0,0,1);
SNMP_CFG->remote_ip = IP4_NONE;
SNMP_CFG->remote_path = agentx_master_addr;
SNMP_CFG->trans_type = SNMP_TRANS_DEFAULT;
SNMP_CFG->bgp_local_id = IP4_NONE;
SNMP_CFG->local_port = 0;
SNMP_CFG->remote_port = 705;

View File

@ -122,6 +122,7 @@
// TODO: remove me
#include "proto/bgp/bgp.h"
const char agentx_master_addr[] = AGENTX_MASTER_ADDR;
static void snmp_start_locked(struct object_lock *lock);
static void snmp_sock_err(sock *sk, int err);
@ -170,6 +171,7 @@ int
snmp_set_state(struct snmp_proto *p, enum snmp_proto_state state)
{
enum snmp_proto_state last = p->state;
const struct snmp_config *cf = (struct snmp_config *) p->p.cf;
TRACE(D_EVENTS, "SNMP changing state to %u", state);
@ -193,31 +195,50 @@ snmp_set_state(struct snmp_proto *p, enum snmp_proto_state state)
case SNMP_INIT:
DBG("snmp -> SNMP_INIT\n");
ASSERT(last == SNMP_DOWN);
struct object_lock *lock;
lock = p->lock = olock_new(p->pool);
/*
* lock->addr
* lock->port
* lock->iface
* lock->vrf
*/
lock->type = OBJLOCK_TCP;
lock->hook = snmp_start_locked;
lock->data = p;
olock_acquire(lock);
return PS_START;
if (cf->trans_type == SNMP_TRANS_TCP)
{
/* We need to lock the IP address */
struct object_lock *lock;
lock = p->lock = olock_new(p->pool);
/*
* lock->iface
* lock->vrf
*/
lock->addr = ipa_from_ip4(cf->remote_ip);
lock->port = cf->remote_port;
lock->type = OBJLOCK_TCP;
lock->hook = snmp_start_locked;
lock->data = p;
olock_acquire(lock);
return PS_START;
}
p->state = state = SNMP_LOCKED;
/* Fall thru */
case SNMP_LOCKED:
DBG("snmp -> SNMP_LOCKED\n");
ASSERT(last == SNMP_INIT || SNMP_RESET);
sock *s = sk_new(p->pool);
s->type = SK_TCP_ACTIVE;
s->saddr = ipa_from_ip4(p->local_ip);
s->daddr = ipa_from_ip4(p->remote_ip);
s->dport = p->remote_port;
s->rbsize = SNMP_RX_BUFFER_SIZE;
s->tbsize = SNMP_TX_BUFFER_SIZE;
if (cf->trans_type == SNMP_TRANS_TCP)
{
s->type = SK_TCP_ACTIVE;
s->saddr = ipa_from_ip4(p->local_ip);
s->daddr = ipa_from_ip4(p->remote_ip);
s->dport = p->remote_port;
s->rbsize = SNMP_RX_BUFFER_SIZE;
s->tbsize = SNMP_TX_BUFFER_SIZE;
}
else
{
s->type = SK_UNIX_ACTIVE;
s->host = cf->remote_path; /* daddr */
s->rbsize = SNMP_RX_BUFFER_SIZE;
s->tbsize = SNMP_TX_BUFFER_SIZE;
}
/* s->tos = IP_PREC_INTERNET_CONTROL */
s->tx_hook = snmp_connected;
@ -241,12 +262,14 @@ snmp_set_state(struct snmp_proto *p, enum snmp_proto_state state)
p->sock->rx_hook = snmp_rx;
p->sock->tx_hook = NULL;
snmp_start_subagent(p);
// handle no response (for long time)
p->startup_timer->hook = snmp_stop_timeout;
tm_start(p->startup_timer, 1 S);
return PS_START;
case SNMP_REGISTER:
DBG("snmp -> SNMP_REGISTER\n");
ASSERT(last == SNMP_OPEN);
tm_stop(p->startup_timer); /* stop timeout */
snmp_register_mibs(p);
return PS_START;
@ -276,6 +299,7 @@ snmp_set_state(struct snmp_proto *p, enum snmp_proto_state state)
DBG("snmp -> SNMP_RESET\n");
ASSUME(last == SNMP_REGISTER || last == SNMP_CONN);
ASSUME(p->sock);
snmp_stop_subagent(p);
p->sock->rx_hook = snmp_rx_skip;
p->sock->tx_hook = snmp_tx_skip;
return PS_STOP;
@ -612,8 +636,10 @@ snmp_show_proto_info(struct proto *P)
static void
snmp_postconfig(struct proto_config *CF)
{
const struct snmp_config *cf = (struct snmp_config *) CF;
/* Walk the BGP protocols and cache their references. */
if (((struct snmp_config *) CF)->bgp_local_as == 0)
if (cf->bgp_local_as == 0)
cf_error("local as not specified");
}

View File

@ -29,6 +29,8 @@
#define SNMP_TX_BUFFER_SIZE 8192
#define SNMP_PKT_SIZE_MAX 4098
#define AGENTX_MASTER_ADDR "/var/agentx/master"
enum snmp_proto_state {
SNMP_DOWN = 0,
SNMP_INIT = 1,
@ -46,12 +48,20 @@ struct snmp_bond {
u8 type;
};
enum snmp_transport_type {
SNMP_TRANS_DEFAULT,
SNMP_TRANS_UNIX,
SNMP_TRANS_TCP,
};
struct snmp_config {
struct proto_config cf;
enum snmp_transport_type trans_type;
ip4_addr local_ip;
ip4_addr remote_ip;
u16 local_port;
ip4_addr remote_ip; /* master agentx IP address for TCP transport */
u16 remote_port;
const char *remote_path; /* master agentx UNIX socket name */
ip4_addr bgp_local_id; /* BGP4-MIB related fields */
u32 bgp_local_as;
@ -67,7 +77,7 @@ struct snmp_config {
* We use this fact to check differences of
* nonallocated parts of configs with memcpy
*/
//const struct oid *oid_identifier; TODO
//const struct oid *oid_identifier; TODO
};
#define SNMP_BGP_P_REGISTERING 0x01
@ -84,6 +94,7 @@ struct snmp_registered_oid {
struct oid *oid;
};
struct snmp_proto {
struct proto p;
struct object_lock *lock;
@ -153,4 +164,6 @@ int snmp_set_state(struct snmp_proto *p, enum snmp_proto_state state);
void snmp_reset(struct snmp_proto *p);
extern const char agentx_master_addr[sizeof(AGENTX_MASTER_ADDR)];
#endif