mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-12-22 09:41:54 +00:00
TMP: compiles, some pdus working
This commit is contained in:
parent
a5bdba428b
commit
7961bbb26a
@ -9,6 +9,8 @@
|
||||
#ifndef _BIRD_LISTS_H_
|
||||
#define _BIRD_LISTS_H_
|
||||
|
||||
#include "lib/birdlib.h"
|
||||
|
||||
/*
|
||||
* I admit the list structure is very tricky and also somewhat awkward,
|
||||
* but it's both efficient and easy to manipulate once one understands the
|
||||
|
@ -1,8 +1,8 @@
|
||||
src := snmp.c bgp_mib.c subagent.c
|
||||
src := snmp.c subagent.c
|
||||
obj := $(src-o-files)
|
||||
LIBS += `net-snmp-config --agent-libs`
|
||||
$(all-daemon)
|
||||
$(cf-local)
|
||||
$(call proto-build,snmp_build_)
|
||||
$(call proto-build,snmp_build)
|
||||
|
||||
tests_objs := $(tests_objs) $(src-o-files)
|
||||
|
@ -24,15 +24,16 @@
|
||||
#undef PACKAGE_TARNAME
|
||||
#undef PACKAGE_VERSION
|
||||
|
||||
#include "proto/snmp/bgp_mib.h"
|
||||
#include "lib/birdlib.h"
|
||||
#include "bgp_mib.h"
|
||||
#include "snmp.h"
|
||||
|
||||
static int
|
||||
bgpPeerTable_handler(
|
||||
netsnmp_mib_handler *handler, // contains void * for internal use
|
||||
netsnmp_handler_registration *reginfo,
|
||||
netsnmp_agent_request_info *reqinfo,
|
||||
netsnmp_request_info *requests) {
|
||||
netsnmp_request_info *requests)
|
||||
{
|
||||
|
||||
/* perform anything here that you need to do. The requests have
|
||||
already been processed by the master table_dataset handler, but
|
||||
|
@ -28,15 +28,32 @@ snmp_proto:
|
||||
snmp_proto_start '{'
|
||||
| snmp_proto proto_item ';'
|
||||
| snmp_proto snmp_bgp_bond ';'
|
||||
| snmp_proto ';'
|
||||
| snmp_proto LOCAL PORT expr ';' { SNMP_CFG->local_port = $4; if (($4<1) ||
|
||||
($4>65535)) cf_error("Invalid port number"); }
|
||||
| snmp_proto REMOTE PORT expr ';' { SNMP_CFG->remote_port = $4; if (($4<1) ||
|
||||
($4>65545)) cf_error("Invalid port number"); }
|
||||
| snmp_proto LOCAL ipa ';' { SNMP_CFG->local_ip = $3; }
|
||||
| snmp_proto REMOTE ipa ';' { SNMP_CFG->remote_ip = $3; if(!ipa_nonzero($3))
|
||||
cf_error("Invalid remote ip address"); }
|
||||
;
|
||||
|
||||
snmp_proto_start: proto_start SNMP
|
||||
{
|
||||
this_proto = proto_config_new(&proto_snmp, $1);
|
||||
init_list(&SNMP_CFG->bgp_entries);
|
||||
|
||||
SNMP_CFG->local_ip = IPA_NONE;
|
||||
SNMP_CFG->remote_ip = ipa_build4(127,0,0,1);
|
||||
SNMP_CFG->local_port = 0;
|
||||
SNMP_CFG->remote_port = 705;
|
||||
|
||||
SNMP_CFG->timeout = 15;
|
||||
}
|
||||
|
||||
proto_name ;
|
||||
|
||||
|
||||
|
||||
snmp_bgp_bond: BGP symbol
|
||||
{
|
||||
struct snmp_bond *this_bond = cfg_alloc(sizeof(struct snmp_bond));
|
||||
|
@ -11,53 +11,142 @@
|
||||
*/
|
||||
|
||||
#include "nest/bird.h"
|
||||
#include "nest/protocol.h"
|
||||
#include "nest/cli.h"
|
||||
#include "nest/locks.h"
|
||||
#include "lib/socket.h"
|
||||
|
||||
#include "proto/snmp/snmp.h"
|
||||
#include "proto/snmp/subagent.h"
|
||||
#include "proto/snmp/bgp_mib.h"
|
||||
#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);
|
||||
|
||||
static struct proto *
|
||||
snmp_init(struct proto_config *CF)
|
||||
{
|
||||
struct proto *P = proto_new(CF);
|
||||
struct snmp_proto *p = (void *) P;
|
||||
struct snmp_proto *p = SKIP_BACK(struct snmp_proto, p, P);
|
||||
struct snmp_config *cf = SKIP_BACK(struct snmp_config, cf, CF);
|
||||
|
||||
p->rl_gen = (struct tbf) TBF_DEFAULT_LOG_LIMITS;
|
||||
|
||||
p->local_ip = cf->local_ip;
|
||||
p->remote_ip = cf->remote_ip;
|
||||
p->local_port = cf->local_port;
|
||||
p->remote_port = cf->remote_port;
|
||||
|
||||
// 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);
|
||||
|
||||
return P;
|
||||
}
|
||||
|
||||
void start_multihook(void)
|
||||
static void
|
||||
snmp_start_locked(struct object_lock *lock)
|
||||
{
|
||||
/* init bgp MIB table */
|
||||
snmp_init_bgp_table();
|
||||
log(L_INFO "snmp_start_locked() - preparing socket ");
|
||||
struct snmp_proto *p = lock->data;
|
||||
|
||||
/* init ospf MIB table */
|
||||
//snmp_inti_ospf_table();
|
||||
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;
|
||||
|
||||
// s->tos = IP_PREC_INTERNET_CONTROL
|
||||
//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)
|
||||
{
|
||||
log(L_INFO "snmp_tx() recieved something, yay!");
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static void
|
||||
snmp_sock_err(sock *sk UNUSED, int err UNUSED)
|
||||
{
|
||||
log(L_INFO "snmp_sock_err() ");
|
||||
}
|
||||
|
||||
static int
|
||||
snmp_start(struct proto *P)
|
||||
{
|
||||
/* init MIB tables */
|
||||
if (snmp_start_subagent(start_multihook))
|
||||
return PS_UP;
|
||||
else
|
||||
return PS_DOWN;
|
||||
log(L_INFO "snmp_start() - starting timer (almost)");
|
||||
struct snmp_proto *p = (void *) P;
|
||||
|
||||
p->ping_timer = tm_new_init(p->p.pool, snmp_ping_timer, p, 0, 0);
|
||||
tm_set(p->ping_timer, current_time() + (7 S_));
|
||||
|
||||
/* starting agentX communicaiton channel */
|
||||
log(L_INFO "preparing lock");
|
||||
struct object_lock *lock;
|
||||
lock = p->lock = olock_new(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);
|
||||
|
||||
return PS_START;
|
||||
}
|
||||
|
||||
static int
|
||||
snmp_reconfigure(struct proto *P, struct proto_config *CF)
|
||||
{
|
||||
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;
|
||||
p->timeout = 15;
|
||||
|
||||
log(L_INFO "snmp_reconfigure() lip: %I:%u rip: %I:%u",
|
||||
p->local_ip, p->local_port, p->remote_ip, p->remote_port);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
snmp_show_proto_info(struct proto *P)
|
||||
{
|
||||
struct snmp_proto *sp = (void *) P;
|
||||
//struct snmp_proto *sp = (void *) P;
|
||||
struct snmp_config *c = (void *) P->cf;
|
||||
|
||||
cli_msg(-1006, " BGP peers");
|
||||
@ -66,7 +155,6 @@ snmp_show_proto_info(struct proto *P)
|
||||
{
|
||||
struct proto_config *cf = P->cf;
|
||||
struct bgp_config *bcf = (struct bgp_config *) cf;
|
||||
struct proto_config *pcf = (void *) bond->proto;
|
||||
struct proto *p = cf->proto;
|
||||
struct bgp_proto *bp = (struct bgp_proto *) cf->proto;
|
||||
struct bgp_conn *conn = bp->conn;
|
||||
@ -83,10 +171,12 @@ snmp_show_proto_info(struct proto *P)
|
||||
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);
|
||||
/*
|
||||
if (conn) {
|
||||
cli_msg(-1006, " state: %u", conn->state);
|
||||
cli_msg(-1006, " remote as: %u", conn->remote_caps->as4_number);
|
||||
}
|
||||
*/
|
||||
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);
|
||||
@ -98,10 +188,12 @@ bp->stats.fsm_established_transitions);
|
||||
cli_msg(-1006, " fsm total time: --");
|
||||
cli_msg(-1006, " retry interval: %u", bcf->connect_retry_time);
|
||||
|
||||
/*
|
||||
if (conn) {
|
||||
cli_msg(-1006, " hold time: %u", conn->hold_time);
|
||||
cli_msg(-1006, " keep alive: %u", conn->keepalive_time );
|
||||
}
|
||||
*/
|
||||
|
||||
cli_msg(-1006, " hold configurated: %u", bcf->hold_time );
|
||||
cli_msg(-1006, " keep alive config: %u", bcf->keepalive_time );
|
||||
@ -119,19 +211,22 @@ bp->stats.fsm_established_transitions);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
shutdown_multihook(void)
|
||||
static void
|
||||
snmp_ping_timer(struct timer *tm)
|
||||
{
|
||||
snmp_del_bgp_table();
|
||||
//snmp_del_ospf_table();
|
||||
log(L_INFO "snmp_ping_timer() ");
|
||||
struct snmp_proto *p = tm->data;
|
||||
|
||||
// ping here
|
||||
ping_pdu(p);
|
||||
}
|
||||
|
||||
/* snmp_shutdown already occupied by net-snmp */
|
||||
void
|
||||
snmp_shutdown_(struct proto *P)
|
||||
static int
|
||||
snmp_shutdown(struct proto *P)
|
||||
{
|
||||
snmp_stop_subagent(shutdown_multihook);
|
||||
struct snmp_proto *p = SKIP_BACK(struct snmp_proto, p, P);
|
||||
snmp_stop_subagent(p);
|
||||
}
|
||||
|
||||
struct protocol proto_snmp = {
|
||||
@ -143,13 +238,13 @@ struct protocol proto_snmp = {
|
||||
.init = snmp_init,
|
||||
.start = snmp_start,
|
||||
.reconfigure = snmp_reconfigure,
|
||||
.shutdown = snmp_shutdown_,
|
||||
.shutdown = snmp_shutdown,
|
||||
.show_proto_info = snmp_show_proto_info,
|
||||
};
|
||||
|
||||
/* strange name because conflict with net-snmp lib snmp_lib() */
|
||||
/* strange name because of conflict with net-snmp lib snmp_lib() */
|
||||
void
|
||||
snmp_build_(void)
|
||||
snmp_build(void)
|
||||
{
|
||||
proto_build(&proto_snmp);
|
||||
}
|
||||
|
@ -8,15 +8,26 @@
|
||||
*/
|
||||
|
||||
#ifndef _BIRD_SNMP_H_
|
||||
#define _BIRD_SNPM_H_
|
||||
#define _BIRD_SNMP_H_
|
||||
|
||||
#include "lib/ip.h"
|
||||
#include "lib/socket.h"
|
||||
#include "lib/timer.h"
|
||||
#include "nest/bird.h"
|
||||
#include "nest/protocol.h"
|
||||
#include "proto/bgp/bgp.h"
|
||||
|
||||
|
||||
#define SNMP_UNDEFINED 0
|
||||
#define SNMP_BGP 1
|
||||
#define SNMP_OSPF 2
|
||||
#define SNMP_INVALID 255
|
||||
|
||||
#define SNMP_PORT 705
|
||||
|
||||
#define SNMP_RX_BUFFER_SIZE 2048
|
||||
#define SNMP_TX_BUFFER_SIZE 2048
|
||||
|
||||
struct snmp_bond {
|
||||
node n;
|
||||
struct proto_config *proto;
|
||||
@ -24,13 +35,32 @@ struct snmp_bond {
|
||||
};
|
||||
|
||||
struct snmp_config {
|
||||
struct channel_config c;
|
||||
struct proto_config cf;
|
||||
ip_addr local_ip;
|
||||
ip_addr remote_ip;
|
||||
u16 local_port;
|
||||
u16 remote_port;
|
||||
u8 timeout;
|
||||
//struct iface *iface;
|
||||
list bgp_entries;
|
||||
};
|
||||
|
||||
struct snmp_proto {
|
||||
struct channel c;
|
||||
struct proto p;
|
||||
struct object_lock *lock;
|
||||
ip_addr local_ip;
|
||||
ip_addr remote_ip;
|
||||
u16 local_port;
|
||||
u16 remote_port;
|
||||
sock *sock;
|
||||
u8 timeout;
|
||||
u32 session_id;
|
||||
u32 transaction_id;
|
||||
u32 packet_id;
|
||||
//struct iface *iface;
|
||||
// map goes here
|
||||
struct tbf rl_gen;
|
||||
timer *ping_timer;
|
||||
};
|
||||
|
||||
struct snmp_channel_config {
|
||||
@ -43,4 +73,6 @@ struct snmp_channel {
|
||||
struct channel c;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -6,89 +6,412 @@
|
||||
*
|
||||
* Can be freely distributed and used under the terms of the GNU GPL.
|
||||
*
|
||||
* Parts of this file were auto-generated from net-snmp-config
|
||||
*/
|
||||
|
||||
#include <net-snmp/net-snmp-config.h>
|
||||
#include "lib/unaligned.h"
|
||||
#include "subagent.h"
|
||||
|
||||
#ifdef HAVE_SIGNAL
|
||||
#include <signal.h>
|
||||
#endif
|
||||
static int parse_response(struct snmp_proto *p, byte *buf, uint size);
|
||||
static void header_update_len(byte *buf, u32 len);
|
||||
static uint oid_size(struct oid* o);
|
||||
|
||||
#ifdef HAV_SYS_STAT_H
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
static const char * const snmp_errs[] = {
|
||||
#define SNMP_ERR_SHIFT 256
|
||||
[AGENTX_RES_OPEN_FAILED - SNMP_ERR_SHIFT] = "Open failed",
|
||||
[AGENTX_RES_NOT_OPEN - SNMP_ERR_SHIFT] = "Not open",
|
||||
[AGENTX_RES_INDEX_WRONG_TYPE - SNMP_ERR_SHIFT] = "Index wrong type",
|
||||
[AGENTX_RES_INDEX_ALREADY_ALLOC - SNMP_ERR_SHIFT] = "Index already allocated",
|
||||
[AGENTX_RES_INDEX_NONE_AVAIL - SNMP_ERR_SHIFT] = "Index none availlable",
|
||||
[AGENTX_RES_NOT_ALLOCATED - SNMP_ERR_SHIFT] = "Not allocated",
|
||||
[AGENTX_RES_UNSUPPORTED_CONTEXT - SNMP_ERR_SHIFT] = "Unsupported contex",
|
||||
[AGENTX_RES_DUPLICATE_REGISTR - SNMP_ERR_SHIFT] = "Duplicate registration",
|
||||
[AGENTX_RES_UNKNOWN_REGISTR - SNMP_ERR_SHIFT] = "Unknown registration",
|
||||
[AGENTX_RES_UNKNOWN_AGENT_CAPS - SNMP_ERR_SHIFT] = "Unknown agent caps",
|
||||
[AGENTX_RES_PARSE_ERROR - SNMP_ERR_SHIFT] = "Parse error",
|
||||
[AGENTX_RES_REQUEST_DENIED - SNMP_ERR_SHIFT] = "Request denied",
|
||||
[AGENTX_RES_PROCESSING_ERR - SNMP_ERR_SHIFT] = "Processing error",
|
||||
};
|
||||
|
||||
#ifdef HAVE_FCNTL_H
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
#include <net-snmp/net-snmp-includes.h>
|
||||
#include <net-snmp/agent/net-snmp-agent-includes.h>
|
||||
|
||||
extern int netsnmp_running;
|
||||
|
||||
int
|
||||
snmp_start_subagent(void (*hook)(void))
|
||||
static int
|
||||
put_str(byte *buf, const char *str, uint *size)
|
||||
{
|
||||
/* subagent mode */
|
||||
netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID,
|
||||
NETSNMP_DS_AGENT_ROLE, 1);
|
||||
uint len = strlen(str);
|
||||
uint pkt_len = BIRD_ALIGN(len, 4);
|
||||
|
||||
/* forking netsnmp mechanism * /
|
||||
if (netsnmp_daemonize(1, snmp_stderrolog_status()) != 0)
|
||||
return 0; // start FAILED
|
||||
*/
|
||||
if (len > MAX_STR)
|
||||
return -1;
|
||||
|
||||
/* for Win32 only */
|
||||
SOCK_STARTUP;
|
||||
put_u32(buf, len);
|
||||
|
||||
memcpy(buf + 4, str, len);
|
||||
|
||||
/* init library */
|
||||
init_agent("bird");
|
||||
// make the value 32-bit aligned
|
||||
for (uint i = 0; i < pkt_len - len; i++)
|
||||
buf[len + i] = 0x00; // PADDING
|
||||
|
||||
if (hook)
|
||||
hook();
|
||||
*size += (4 + pkt_len);
|
||||
|
||||
/* used for loading config 'bird-snmp.conf' */
|
||||
init_snmp("bird-snmp");
|
||||
|
||||
return 1; // SUCCESS
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
put_blank(byte *buf, uint *size)
|
||||
{
|
||||
buf[0] = buf[1] = buf[2] = buf[3] = 0;
|
||||
*size += 4;
|
||||
}
|
||||
|
||||
static void
|
||||
put_oid(byte *buf, struct oid *oid, uint *size)
|
||||
{
|
||||
put_u8(buf, oid->n_subid);
|
||||
put_u8(buf + 1, oid->prefix);
|
||||
put_u8(buf + 2, oid->include);
|
||||
put_u8(buf + 3, 0); // PADDING
|
||||
|
||||
put_u32s(buf + 4, oid->subid.ids, oid->subid.len);
|
||||
|
||||
*size += (4 + oid->subid.len);
|
||||
}
|
||||
|
||||
/* paste data at first byte in message
|
||||
* with 3B of padding
|
||||
*/
|
||||
static void
|
||||
paste_fbyte(byte *buf, u8 data, uint *size)
|
||||
{
|
||||
buf[0] = data;
|
||||
buf[1] = buf[2] = buf[3] = 0x00; // PADDING
|
||||
*size += 4;
|
||||
}
|
||||
|
||||
static u32
|
||||
store_in_order(u32 val, int order)
|
||||
{
|
||||
/* AGENTX_BIG_ENDIAN */
|
||||
if (order)
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
open_pdu(struct snmp_proto *p, struct oid *oid)
|
||||
{
|
||||
sock *sk = p->sock;
|
||||
byte *buf, *pkt, *end;
|
||||
buf = pkt = sk->tbuf;
|
||||
uint size = sk->tbsize;
|
||||
|
||||
// should be configurable
|
||||
const char *str = "bird";
|
||||
|
||||
uint pkt_size = 0;
|
||||
uint slen = BIRD_ALIGN(strlen(str), 4);
|
||||
|
||||
/* +8 - header of oid (4) and octet string length (4) */
|
||||
if (size > AGENTX_HEADER_SIZE + oid->subid.len + slen + 8)
|
||||
{
|
||||
log(L_INFO "open_pdu() sufficient size nw order: %u",
|
||||
AGENTX_NETWORK_BYTE_ORDER);
|
||||
PASTE_HEADER(pkt, AGENTX_OPEN_PDU, AGENTX_NETWORK_BYTE_ORDER, size);
|
||||
|
||||
// use random num instead
|
||||
put_u32(&h->session_id, 1);
|
||||
put_u32(&h->transaction_id, 1);
|
||||
put_u32(&h->packet_id, 1);
|
||||
|
||||
paste_fbyte(pkt, p->timeout, &pkt_size);
|
||||
ADVANCE(pkt, size, 4);
|
||||
|
||||
put_oid(pkt, oid, &pkt_size);
|
||||
ADVANCE(pkt, size, oid_size(oid));
|
||||
|
||||
/* paste description */
|
||||
put_str(pkt, str, &pkt_size);
|
||||
ADVANCE(pkt, size, slen);
|
||||
|
||||
header_update_len(buf, pkt_size);
|
||||
|
||||
log(L_INFO "sk_send()-ing %u", AGENTX_HEADER_SIZE + pkt_size);
|
||||
int ret = sk_send(sk, AGENTX_HEADER_SIZE + pkt_size);
|
||||
if (ret == 0)
|
||||
log(L_INFO "sleep");
|
||||
else if (ret < 0)
|
||||
log(L_INFO "err %d", ret);
|
||||
else
|
||||
log(L_INFO "ok !!! ");
|
||||
}
|
||||
|
||||
else
|
||||
log(L_INFO "open_pdu() insufficient size, %u <= %u ",
|
||||
size, AGENTX_HEADER_SIZE + oid->subid.len + slen + 8);
|
||||
}
|
||||
|
||||
static void
|
||||
close_pdu(struct snmp_proto *p, u8 reason)
|
||||
{
|
||||
sock *sk = p->sock;
|
||||
byte *buf, *pkt;
|
||||
buf = pkt = sk->tbuf;
|
||||
uint size = sk->tbsize;
|
||||
log(L_INFO "close_pdu() size: %u %c %u", size, (size > AGENTX_HEADER_SIZE + 4)
|
||||
? '>':'<', AGENTX_HEADER_SIZE);
|
||||
|
||||
/* +4B for reason */
|
||||
if (size > AGENTX_HEADER_SIZE + 4)
|
||||
{
|
||||
PASTE_HEADER(buf, AGENTX_CLOSE_PDU, AGENTX_NETWORK_BYTE_ORDER, size);
|
||||
|
||||
log(L_INFO "session_id %u", p->session_id);
|
||||
h->session_id = p->session_id;
|
||||
p->transaction_id++;
|
||||
p->transaction_id = get_u32(&p->transaction_id);
|
||||
put_u32(&h->transaction_id, p->transaction_id);
|
||||
put_u32(&h->packet_id, 1);
|
||||
|
||||
ADVANCE(pkt, size, sizeof(struct agentx_header));
|
||||
|
||||
paste_fbyte(pkt, reason, &size);
|
||||
ADVANCE(pkt, size, 4);
|
||||
|
||||
/* 4 - reason size */
|
||||
header_update_len(sk->tbuf, 4);
|
||||
|
||||
int ret = sk_send(sk, sizeof(struct agentx_header) + 4);
|
||||
|
||||
if (ret == 0)
|
||||
log(L_INFO "sleep");
|
||||
else if (ret < 0)
|
||||
log(L_INFO "err");
|
||||
else
|
||||
log(L_INFO, "ok !! ");
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
parse_pkt(struct snmp_proto *p, byte *buf, uint size)
|
||||
{
|
||||
if (size < AGENTX_HEADER_SIZE)
|
||||
return 0;
|
||||
|
||||
struct agentx_header *h = (void *) buf;
|
||||
switch (h->type)
|
||||
{
|
||||
case AGENTX_RESPONSE_PDU:
|
||||
return parse_response(p, buf, size);
|
||||
break;
|
||||
|
||||
/* should not happen */
|
||||
default:
|
||||
die("unknown packet type");
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
parse_response(struct snmp_proto *p, byte *buf, uint size)
|
||||
{
|
||||
if (size < sizeof(struct agentx_response))
|
||||
return 0;
|
||||
|
||||
struct agentx_response *r = (void *) buf;
|
||||
struct agentx_header *h = &r->h;
|
||||
|
||||
log(L_INFO "endianity: %s, session %u", (h->flags & AGENTX_NETWORK_BYTE_ORDER) ? "big end":
|
||||
"little end", h->session_id);
|
||||
p->session_id = h->session_id;
|
||||
p->transaction_id = h->transaction_id;
|
||||
p->packet_id = h->packet_id;
|
||||
|
||||
log(L_INFO "size %u", get_u32(&h->payload));
|
||||
log(L_INFO "uptime: %u s", get_u32(&r->uptime));
|
||||
switch (r->err)
|
||||
{
|
||||
case AGENTX_RES_NO_ERROR:
|
||||
break;
|
||||
default:
|
||||
log(L_INFO "an error occured: '%s'", snmp_errs[get_u16(&r->err) -
|
||||
SNMP_ERR_SHIFT]);
|
||||
break;
|
||||
}
|
||||
proto_notify_state(&p->p, PS_UP);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
header_update_len(byte *buf, u32 len)
|
||||
{
|
||||
struct agentx_header *h = (void *) buf;
|
||||
put_u32(&h->payload, len);
|
||||
log(L_INFO "header_update_len() %d 0x%02X 0x%02X 0x%02X 0x%02X", len, *((unsigned char
|
||||
*) &h->payload), *(((unsigned char *) &h->payload) + 1), *(((unsigned char *)
|
||||
&h->payload) + 2), *(((unsigned char *) &h->payload) + 3));
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
snmp_start_subagent(struct snmp_proto *p)
|
||||
{
|
||||
log(L_INFO "snmp_start_subagent() starting subagent");
|
||||
|
||||
/* blank oid means unsupported */
|
||||
struct oid *o = mb_allocz(p->p.pool, sizeof(struct oid));
|
||||
open_pdu(p, o);
|
||||
mb_free(o);
|
||||
}
|
||||
|
||||
void
|
||||
snmp_stop_subagent(struct snmp_proto *p)
|
||||
{
|
||||
sock *sk = p->sock;
|
||||
|
||||
close_pdu(p, AGENTX_CLOSE_SHUTDOWN);
|
||||
|
||||
sk->rx_hook = snmp_stop_ack;
|
||||
}
|
||||
|
||||
static uint
|
||||
oid_size(struct oid *o)
|
||||
{
|
||||
return 4 + o->subid.len;
|
||||
}
|
||||
|
||||
int
|
||||
snmp_rx(sock *sk, uint size)
|
||||
{
|
||||
log(L_INFO "snmp_rx()");
|
||||
struct snmp_proto *p = sk->data;
|
||||
byte *pkt = sk->rbuf;
|
||||
byte *end = pkt + size;
|
||||
|
||||
parse_pkt(p, pkt, size);
|
||||
/*
|
||||
while (end >= ptk + AGENTX_HEADER_SIZE)
|
||||
{
|
||||
parse_header(p);
|
||||
parse_pkt(p, );
|
||||
}
|
||||
*/
|
||||
return 0;
|
||||
// 1 means all done
|
||||
}
|
||||
|
||||
void
|
||||
ping_pdu(struct snmp_proto *p)
|
||||
{
|
||||
/* this does not support non-default context */
|
||||
sock *sk = p->sock;
|
||||
byte *buf = sk->tbuf;
|
||||
uint size = sk->tbsize;
|
||||
|
||||
PASTE_HEADER(buf, AGENTX_PING_PDU, AGENTX_NETWORK_BYTE_ORDER, size);
|
||||
|
||||
put_u32(&h->session_id, p->session_id);
|
||||
p->transaction_id++;
|
||||
put_u32(&h->transaction_id, p->transaction_id);
|
||||
put_u32(&h->packet_id, 1);
|
||||
put_u32(&h->payload, 0);
|
||||
|
||||
sk_send(sk, AGENTX_HEADER_SIZE);
|
||||
}
|
||||
|
||||
/*
|
||||
* cont is optional context
|
||||
* upp_b is upper_bond
|
||||
*/
|
||||
int
|
||||
snmp_register_oid(sock *sk, struct oid *subtree, u8 range, const char *cont, u32 upp_b)
|
||||
{
|
||||
struct snmp_proto *p = sk->data;
|
||||
byte *buf = sk->tbuf;
|
||||
uint size = sk->tbsize;
|
||||
log(L_INFO "snmp_register_oid() ");
|
||||
|
||||
u8 flags = AGENTX_NETWORK_BYTE_ORDER | ((cont) ? AGENTX_NON_DEFAULT_CONTEXT :
|
||||
0);
|
||||
PASTE_HEADER(buf, AGENTX_REGISTER_PDU, flags, size);
|
||||
|
||||
if (cont)
|
||||
put_str(buf, cont, &size);
|
||||
|
||||
put_u8(buf, p->timeout);
|
||||
put_u8(buf + 1, AGENTX_PRIORITY);
|
||||
put_u8(buf + 2, range);
|
||||
put_u8(buf + 3, 0); // PADDING
|
||||
ADVANCE(buf, size, 4);
|
||||
|
||||
put_oid(buf, subtree, &size);
|
||||
ADVANCE(buf, size, oid_size(subtree));
|
||||
|
||||
if (upp_b)
|
||||
{
|
||||
put_u32(buf, upp_b);
|
||||
ADVANCE(buf, size, 4);
|
||||
}
|
||||
|
||||
header_update_len(sk->tbuf, buf - sk->tbuf + AGENTX_HEADER_SIZE);
|
||||
|
||||
sk_send(sk, buf - sk->tbuf);
|
||||
}
|
||||
|
||||
/*
|
||||
* cont is optional context nullable
|
||||
* upp_b is upper_bond
|
||||
*/
|
||||
int
|
||||
snmp_unregister_oid(sock *sk, struct oid *subtree, const char *cont, u32 upp_b)
|
||||
{
|
||||
byte *buf = sk->tbuf;
|
||||
uint size = sk->tbsize;
|
||||
log(L_INFO "snmp_unregister_oid()");
|
||||
|
||||
u8 flags = AGENTX_NETWORK_BYTE_ORDER | ((cont) ? AGENTX_NON_DEFAULT_CONTEXT :
|
||||
0);
|
||||
PASTE_HEADER(buf, AGENTX_UNREGISTER_PDU, flags, size);
|
||||
|
||||
if (cont)
|
||||
{
|
||||
put_str(buf, cont, &size);
|
||||
ADVANCE(buf, size, strlen(cont) + 4);
|
||||
}
|
||||
|
||||
put_oid(buf, subtree, &size);
|
||||
ADVANCE(buf, size, oid_size(subtree));
|
||||
|
||||
if (upp_b)
|
||||
{
|
||||
put_u32(buf, upp_b);
|
||||
ADVANCE(buf, size, 4);
|
||||
}
|
||||
|
||||
sk_send(sk, buf - sk->tbuf);
|
||||
}
|
||||
|
||||
static void
|
||||
snmp_stop_ack(sock *sk, uint size)
|
||||
{
|
||||
struct snmp_proto *p = sk->data;
|
||||
byte *buf = sk->rbuf;
|
||||
|
||||
if (size < AGENTX_HEADER_SIZE)
|
||||
return 0;
|
||||
|
||||
if (parse_response(p, buf, size))
|
||||
{
|
||||
p->p.disabled = 1;
|
||||
proto_notify_state(&p->p, PS_DOWN);
|
||||
}
|
||||
}
|
||||
/*
|
||||
void
|
||||
snmp_agent_reconfigure(void)
|
||||
{
|
||||
free_config();
|
||||
read_configs();
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
void
|
||||
snmp_shutdown_subagent(void (*hook)(void))
|
||||
{
|
||||
/* at shutdown time */
|
||||
snmp_shutdown("bird");
|
||||
|
||||
/* shutdown hook */
|
||||
if (hook)
|
||||
hook();
|
||||
|
||||
/* shutdown the agent library */
|
||||
shutdown_agent();
|
||||
|
||||
/* for Win32 only */
|
||||
SOCK_CLEANUP;
|
||||
}
|
||||
|
||||
void
|
||||
snmp_stop_subagent(void (*hook)(void))
|
||||
{
|
||||
/* at shutdown time */
|
||||
snmp_shutdown("bird");
|
||||
|
||||
/* deinitialize MIB code */
|
||||
if (hook)
|
||||
hook();
|
||||
|
||||
/* shutdown the agent library */
|
||||
shutdown_agent();
|
||||
}
|
||||
#undef SNMP_ERR_SHIFT
|
||||
|
@ -1,8 +1,148 @@
|
||||
#ifndef _BIRD_SNMP_SUBAGENT_H_
|
||||
#define _BIRD_SNMP_SUBAGENT_H_
|
||||
|
||||
int snmp_start_subagent(void (*hook)(void));
|
||||
void snmp_agent_reconfigure(void);
|
||||
void snmp_stop_subagent(void (*hook)(void));
|
||||
#include "nest/bird.h"
|
||||
#include "snmp.h"
|
||||
|
||||
void snmp_start_subagent(struct snmp_proto *p);
|
||||
void snmp_stop_subagent(struct snmp_proto *p);
|
||||
|
||||
#define AGENTX_INTEGER 2
|
||||
#define AGENTX_OCTET_STRING 4
|
||||
#define AGENTX_NULL 5
|
||||
#define AGENTX_OBJECT_ID 6
|
||||
#define AGENTX_IP_ADDRESS 64
|
||||
#define AGENTX_COUNTER_32 65
|
||||
#define AGENTX_GAUGE_32 66
|
||||
#define AGENTX_TIME_TICKS 67
|
||||
#define AGENTX_OPAQUE 68
|
||||
#define AGENTX_COUNTER_64 70
|
||||
#define AGENTX_NO_SUCH_OBJECT 128
|
||||
#define AGENTX_NO_SUCH_INSTANCE 129
|
||||
#define AGENTX_END_OF_MIB_VIEW 130
|
||||
|
||||
#define AGENTX_PRIORITY 127
|
||||
#define MAX_STR 0xFFFFFFFF
|
||||
|
||||
#define PASTE_HEADER_(buf, v, t, f, s) \
|
||||
memset(buf, 0, sizeof(struct agentx_header)); \
|
||||
struct agentx_header *h = (void *) buf; \
|
||||
log(L_INFO "value : %d", (void *) h == buf? 1:0); \
|
||||
h->version = v; \
|
||||
h->type = t; \
|
||||
h->flags = f; \
|
||||
h->pad = 0; \
|
||||
ADVANCE(buf, s, sizeof(struct agentx_header)); \
|
||||
|
||||
#define PASTE_HEADER(buf, t, f, s) PASTE_HEADER_(buf, AGENTX_VERSION, t, f, s)
|
||||
#define U32_CPY(w, u) memcpy((w), (u), 4); ADVANCE((w), 4, 4);
|
||||
|
||||
struct agentx_header {
|
||||
u8 version;
|
||||
u8 type;
|
||||
u8 flags;
|
||||
u8 pad;
|
||||
u32 session_id;
|
||||
u32 transaction_id;
|
||||
u32 packet_id;
|
||||
u32 payload; /* length of the packet without header */
|
||||
};
|
||||
|
||||
#define AGENTX_HEADER_SIZE sizeof(struct agentx_header)
|
||||
|
||||
struct subid{
|
||||
u32 len;
|
||||
u32 ids[];
|
||||
};
|
||||
|
||||
struct oid {
|
||||
u8 n_subid;
|
||||
u8 prefix;
|
||||
u8 include;
|
||||
u8 pad;
|
||||
struct subid subid;
|
||||
};
|
||||
|
||||
struct agentx_varbind {
|
||||
u16 type;
|
||||
u16 pad;
|
||||
/* oid part */
|
||||
struct oid name;
|
||||
};
|
||||
|
||||
struct agentx_search_range {
|
||||
struct oid start;
|
||||
struct oid end;
|
||||
};
|
||||
|
||||
struct agentx_response {
|
||||
struct agentx_header h;
|
||||
u32 uptime;
|
||||
u16 err;
|
||||
u16 index;
|
||||
};
|
||||
|
||||
#define AGENTX_VERSION 1
|
||||
|
||||
enum agentx_pdu {
|
||||
AGENTX_OPEN_PDU = 1,
|
||||
AGENTX_CLOSE_PDU = 2,
|
||||
AGENTX_REGISTER_PDU = 3,
|
||||
AGENTX_UNREGISTER_PDU = 4,
|
||||
AGENTX_GET_PDU = 5,
|
||||
AGENTX_GET_NEXT_PDU = 6,
|
||||
AGENTX_GET_BULK_PDU = 7,
|
||||
AGENTX_TEST_SET_PDU = 8,
|
||||
AGENTX_COMMIT_SET_PDU = 9,
|
||||
AGENTX_UNDO_SET_PDU = 10,
|
||||
AGENTX_CLEANUP_SET_PDU = 11,
|
||||
AGENTX_NOTIFY_PDU = 12,
|
||||
AGENTX_PING_PDU = 13,
|
||||
AGENTX_INDEX_ALLOCATE_PDU = 14,
|
||||
AGENTX_INDEX_DEALLOCATE_PDU = 15,
|
||||
AGENTX_ADD_AGENT_CAPS_PDU = 16,
|
||||
AGENTX_REMOVE_AGENT_CAPS_PDU = 17,
|
||||
AGENTX_RESPONSE_PDU = 18,
|
||||
} PACKED;
|
||||
|
||||
#define AGENTX_FLAGS_MASK 0x1F
|
||||
|
||||
enum agentx_flags {
|
||||
AGENTX_FLAG_INSTANCE_REGISTRATION = 0x01,
|
||||
AGENTX_FLAG_NEW_INDEX = 0x02,
|
||||
AGENTX_FLAG_ANY_INDEX = 0x04,
|
||||
AGENTX_NON_DEFAULT_CONTEXT = 0x08,
|
||||
AGENTX_NETWORK_BYTE_ORDER = 0x10,
|
||||
} PACKED;
|
||||
|
||||
/* CLOSE_PDU close reasons */
|
||||
enum agentx_close_reasons {
|
||||
AGENTX_CLOSE_OTHER = 1,
|
||||
AGENTX_CLOSE_PARSE_ERROR = 2,
|
||||
AGENTX_CLOSE_PROTOCOL_ERROR = 3,
|
||||
AGENTX_CLOSE_TIMEOUTS = 4,
|
||||
AGENTX_CLOSE_SHUTDOWN = 5,
|
||||
AGENTX_CLOSE_BY_MANAGER = 6,
|
||||
} PACKED;
|
||||
|
||||
|
||||
/* RESPONSE_PDU - result error */
|
||||
enum agentx_response_err {
|
||||
AGENTX_RES_NO_ERROR = 0,
|
||||
AGENTX_RES_OPEN_FAILED = 256,
|
||||
AGENTX_RES_NOT_OPEN = 257,
|
||||
AGENTX_RES_INDEX_WRONG_TYPE = 258,
|
||||
AGENTX_RES_INDEX_ALREADY_ALLOC = 259,
|
||||
AGENTX_RES_INDEX_NONE_AVAIL = 260,
|
||||
AGENTX_RES_NOT_ALLOCATED = 261,
|
||||
AGENTX_RES_UNSUPPORTED_CONTEXT = 262,
|
||||
AGENTX_RES_DUPLICATE_REGISTR = 263,
|
||||
AGENTX_RES_UNKNOWN_REGISTR = 264,
|
||||
AGENTX_RES_UNKNOWN_AGENT_CAPS = 265,
|
||||
AGENTX_RES_PARSE_ERROR = 266,
|
||||
AGENTX_RES_REQUEST_DENIED = 267,
|
||||
AGENTX_RES_PROCESSING_ERR = 268,
|
||||
} PACKED;
|
||||
|
||||
int snmp_rx(sock *sk, uint size);
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user