]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
TMP: compiles, some pdus working
authorVojtech Vilimek <vojtech.vilimek@nic.cz>
Wed, 10 Aug 2022 15:31:32 +0000 (17:31 +0200)
committerVojtech Vilimek <vojtech.vilimek@nic.cz>
Wed, 10 Aug 2022 15:31:32 +0000 (17:31 +0200)
lib/lists.h
proto/snmp/Makefile
proto/snmp/bgp_mib.c
proto/snmp/config.Y
proto/snmp/snmp.c
proto/snmp/snmp.h
proto/snmp/subagent.c
proto/snmp/subagent.h

index 86ff59c9cc0b8cca224144f64a707b345b8a7acd..5bfe19f3bb6f3d2778b7c4a3f3b89a33022467ae 100644 (file)
@@ -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
index f121af2576140afd7762a321628e7702525defe7..ca589059c45a9e6c699cb0a55df36d7e6b7e550c 100644 (file)
@@ -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)
index dae6a945e6efb89014e90d1aa4ddc50923bc5e08..6f80acdc056ccf1dd81f620c4c228b396206d991 100644 (file)
 #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
index f50f314b62192e15bd5a40df27db751b63c2ad70..7593ef5f8bdf57d508ea2cd06fd5f519d1a11059 100644 (file)
@@ -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));
index 2bf37d58babe58424a77410d9a181cf046ccfc3c..3f76a4c4607f0208d0c029d364618da5ef3a78b4 100644 (file)
  */
 
 #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;
+
+  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);
+}
 
-  /* init ospf MIB table */
-  //snmp_inti_ospf_table();
+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);
 }
index 57709f5b1e4111e30d9758a6b8872284d8efe224..90236c5cc6dc33663fcfe9515d0e77376720d6bd 100644 (file)
@@ -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
index 5bc81d34ffbc3ceb6515b44d0a2554e2d9856d1a..f7aa4c39b9c4f19a885402156bef2d742f0761c1 100644 (file)
  *
  *     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
+static int
+put_str(byte *buf, const char *str, uint *size)
+{
+  uint len = strlen(str);
+  uint pkt_len = BIRD_ALIGN(len, 4);
 
-#include <net-snmp/net-snmp-includes.h>
-#include <net-snmp/agent/net-snmp-agent-includes.h>
+  if (len > MAX_STR)
+    return -1;
 
-extern int netsnmp_running;
+  put_u32(buf, len);
+  memcpy(buf + 4, str, len);
 
-int
-snmp_start_subagent(void (*hook)(void))
+  // make the value 32-bit aligned
+  for (uint i = 0; i < pkt_len - len; i++)
+    buf[len + i] = 0x00;  // PADDING
+
+  *size += (4 + pkt_len);
+
+  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)
 {
-  /* subagent mode */
-  netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID,
-                        NETSNMP_DS_AGENT_ROLE, 1);
+  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);
 
-  /* forking netsnmp mechanism  * /
-    if (netsnmp_daemonize(1, snmp_stderrolog_status()) != 0)
-      return 0;   // start FAILED
-   */
+  /* +4B for reason */
+  if (size > AGENTX_HEADER_SIZE + 4)
+  {
+    PASTE_HEADER(buf, AGENTX_CLOSE_PDU, AGENTX_NETWORK_BYTE_ORDER, size);
 
-  /* for Win32 only */
-  SOCK_STARTUP;
+    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);
 
-  /* init library */
-  init_agent("bird");
+    ADVANCE(pkt, size, sizeof(struct agentx_header));
+    
+    paste_fbyte(pkt, reason, &size);
+    ADVANCE(pkt, size, 4);
 
-  if (hook)
-    hook();
+    /* 4 - reason size */
+    header_update_len(sk->tbuf, 4);
 
-  /* used for loading config 'bird-snmp.conf' */
-  init_snmp("bird-snmp");
+    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));
 
-  return 1;   // SUCCESS
 }
 
 void
-snmp_agent_reconfigure(void)
+snmp_start_subagent(struct snmp_proto *p)
 {
-  free_config();
-  read_configs();
+  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_shutdown_subagent(void (*hook)(void))
+snmp_stop_subagent(struct snmp_proto *p)
 {
-  /* at shutdown time */
-  snmp_shutdown("bird");
+  sock *sk = p->sock;
+
+  close_pdu(p, AGENTX_CLOSE_SHUTDOWN);
+
+  sk->rx_hook = snmp_stop_ack;
+}
 
-  /* shutdown hook */
-  if (hook)
-    hook();
+static uint
+oid_size(struct oid *o)
+{
+  return 4 + o->subid.len;
+}
 
-  /* shutdown the agent library */
-  shutdown_agent();
+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;
 
-  /* for Win32 only */
-  SOCK_CLEANUP;
+  parse_pkt(p, pkt, size);
+  /* 
+  while (end >= ptk + AGENTX_HEADER_SIZE)
+  {
+    parse_header(p);
+    parse_pkt(p, );
+  }
+  */ 
+  return 0;
+  // 1 means all done 
 }
 
-void
-snmp_stop_subagent(void (*hook)(void))
+void 
+ping_pdu(struct snmp_proto *p)
 {
-  /* at shutdown time */
-  snmp_shutdown("bird");
+  /* 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);
 
-  /* deinitialize MIB code */
-  if (hook)
-    hook();
+  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);
 
-  /* shutdown the agent library */
-  shutdown_agent();
+  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)
+{
+
+}
+*/
+
+#undef SNMP_ERR_SHIFT
index 9cd923572c1aca945102b8ba9e8467d4da11c0bb..71320519a8c6b15d43d1a27b4d97948720c5d461 100644 (file)
@@ -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