summaryrefslogtreecommitdiffstats
path: root/zebra/zebra_snmp.c
diff options
context:
space:
mode:
Diffstat (limited to 'zebra/zebra_snmp.c')
-rw-r--r--zebra/zebra_snmp.c550
1 files changed, 550 insertions, 0 deletions
diff --git a/zebra/zebra_snmp.c b/zebra/zebra_snmp.c
new file mode 100644
index 000000000..d160bfa73
--- /dev/null
+++ b/zebra/zebra_snmp.c
@@ -0,0 +1,550 @@
+/* BGP4 SNMP support
+ * Copyright (C) 1999 Kunihiro Ishiguro
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING. If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include <zebra.h>
+
+#ifdef HAVE_SNMP
+#include <asn1.h>
+#include <snmp.h>
+#include <snmp_impl.h>
+
+#include "if.h"
+#include "log.h"
+#include "prefix.h"
+#include "command.h"
+#include "smux.h"
+#include "table.h"
+
+#include "zebra/rib.h"
+
+#define IPFWMIB 1,3,6,1,2,1,4,24
+#define ZEBRAOID 1,3,6,1,4,1,3317,1,2,1
+
+/* ipForwardTable */
+#define IPFORWARDDEST 1
+#define IPFORWARDMASK 2
+#define IPFORWARDPOLICY 3
+#define IPFORWARDNEXTHOP 4
+#define IPFORWARDIFINDEX 5
+#define IPFORWARDTYPE 6
+#define IPFORWARDPROTO 7
+#define IPFORWARDAGE 8
+#define IPFORWARDINFO 9
+#define IPFORWARDNEXTHOPAS 10
+#define IPFORWARDMETRIC1 11
+#define IPFORWARDMETRIC2 12
+#define IPFORWARDMETRIC3 13
+#define IPFORWARDMETRIC4 14
+#define IPFORWARDMETRIC5 15
+
+/* ipCidrRouteTable */
+#define IPCIDRROUTEDEST 1
+#define IPCIDRROUTEMASK 2
+#define IPCIDRROUTETOS 3
+#define IPCIDRROUTENEXTHOP 4
+#define IPCIDRROUTEIFINDEX 5
+#define IPCIDRROUTETYPE 6
+#define IPCIDRROUTEPROTO 7
+#define IPCIDRROUTEAGE 8
+#define IPCIDRROUTEINFO 9
+#define IPCIDRROUTENEXTHOPAS 10
+#define IPCIDRROUTEMETRIC1 11
+#define IPCIDRROUTEMETRIC2 12
+#define IPCIDRROUTEMETRIC3 13
+#define IPCIDRROUTEMETRIC4 14
+#define IPCIDRROUTEMETRIC5 15
+#define IPCIDRROUTESTATUS 16
+
+#define INTEGER32 ASN_INTEGER
+#define GAUGE32 ASN_GAUGE
+#define ENUMERATION ASN_INTEGER
+#define ROWSTATUS ASN_INTEGER
+#define IPADDRESS ASN_IPADDRESS
+#define OBJECTIDENTIFIER ASN_OBJECT_ID
+
+oid ipfw_oid [] = { IPFWMIB };
+oid zebra_oid [] = { ZEBRAOID };
+
+/* Hook functions. */
+u_char * ipFwNumber ();
+u_char * ipFwTable ();
+u_char * ipCidrNumber ();
+u_char * ipCidrTable ();
+
+struct variable zebra_variables[] =
+{
+ {0, GAUGE32, RONLY, ipFwNumber, 1, {1}},
+ {IPFORWARDDEST, IPADDRESS, RONLY, ipFwTable, 3, {2, 1, 1}},
+ {IPFORWARDMASK, IPADDRESS, RONLY, ipFwTable, 3, {2, 1, 2}},
+ {IPFORWARDPOLICY, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 3}},
+ {IPFORWARDNEXTHOP, IPADDRESS, RONLY, ipFwTable, 3, {2, 1, 4}},
+ {IPFORWARDIFINDEX, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 5}},
+ {IPFORWARDTYPE, ENUMERATION, RONLY, ipFwTable, 3, {2, 1, 6}},
+ {IPFORWARDPROTO, ENUMERATION, RONLY, ipFwTable, 3, {2, 1, 7}},
+ {IPFORWARDAGE, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 8}},
+ {IPFORWARDINFO, OBJECTIDENTIFIER, RONLY, ipFwTable, 3, {2, 1, 9}},
+ {IPFORWARDNEXTHOPAS, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 10}},
+ {IPFORWARDMETRIC1, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 11}},
+ {IPFORWARDMETRIC2, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 12}},
+ {IPFORWARDMETRIC3, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 13}},
+ {IPFORWARDMETRIC4, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 14}},
+ {IPFORWARDMETRIC5, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 15}},
+ {0, GAUGE32, RONLY, ipCidrNumber, 1, {3}},
+ {IPCIDRROUTEDEST, IPADDRESS, RONLY, ipCidrTable, 3, {4, 1, 1}},
+ {IPCIDRROUTEMASK, IPADDRESS, RONLY, ipCidrTable, 3, {4, 1, 2}},
+ {IPCIDRROUTETOS, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 3}},
+ {IPCIDRROUTENEXTHOP, IPADDRESS, RONLY, ipCidrTable, 3, {4, 1, 4}},
+ {IPCIDRROUTEIFINDEX, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 5}},
+ {IPCIDRROUTETYPE, ENUMERATION, RONLY, ipCidrTable, 3, {4, 1, 6}},
+ {IPCIDRROUTEPROTO, ENUMERATION, RONLY, ipCidrTable, 3, {4, 1, 7}},
+ {IPCIDRROUTEAGE, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 8}},
+ {IPCIDRROUTEINFO, OBJECTIDENTIFIER, RONLY, ipCidrTable, 3, {4, 1, 9}},
+ {IPCIDRROUTENEXTHOPAS, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 10}},
+ {IPCIDRROUTEMETRIC1, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 11}},
+ {IPCIDRROUTEMETRIC2, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 12}},
+ {IPCIDRROUTEMETRIC3, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 13}},
+ {IPCIDRROUTEMETRIC4, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 14}},
+ {IPCIDRROUTEMETRIC5, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 15}},
+ {IPCIDRROUTESTATUS, ROWSTATUS, RONLY, ipCidrTable, 3, {4, 1, 16}}
+};
+
+
+u_char *
+ipFwNumber (struct variable *v, oid objid[], size_t *objid_len,
+ int exact, size_t *val_len, WriteMethod **write_method)
+{
+ static int result;
+ struct route_node *np;
+ struct rib *rib;
+
+ if (smux_header_generic(v, objid, objid_len, exact, val_len, write_method) == MATCH_FAILED)
+ return NULL;
+
+ /* Return number of routing entries. */
+ result = 0;
+ for (np = route_top (rib_table_ipv4); np; np = route_next (np))
+ for (rib = np->info; rib; rib = rib->next)
+ result++;
+
+ return (u_char *)&result;
+}
+
+u_char *
+ipCidrNumber (struct variable *v, oid objid[], size_t *objid_len,
+ int exact, size_t *val_len, WriteMethod **write_method)
+{
+ static int result;
+ struct route_node *np;
+ struct rib *rib;
+
+ if (smux_header_generic(v, objid, objid_len, exact, val_len, write_method) == MATCH_FAILED)
+ return NULL;
+
+ /* Return number of routing entries. */
+ result = 0;
+ for (np = route_top (rib_table_ipv4); np; np = route_next (np))
+ for (rib = np->info; rib; rib = rib->next)
+ result++;
+
+ return (u_char *)&result;
+}
+
+int
+in_addr_cmp(u_char *p1, u_char *p2)
+{
+ int i;
+
+ for (i=0; i<4; i++)
+ {
+ if (*p1 < *p2)
+ return -1;
+ if (*p1 > *p2)
+ return 1;
+ p1++; p2++;
+ }
+ return 0;
+}
+
+int
+in_addr_add(u_char *p, int num)
+{
+ int i, ip0;
+
+ ip0 = *p;
+ p += 4;
+ for (i = 3; 0 <= i; i--) {
+ p--;
+ if (*p + num > 255) {
+ *p += num;
+ num = 1;
+ } else {
+ *p += num;
+ return 1;
+ }
+ }
+ if (ip0 > *p) {
+ /* ip + num > 0xffffffff */
+ return 0;
+ }
+
+ return 1;
+}
+
+int proto_trans(int type)
+{
+ switch (type)
+ {
+ case ZEBRA_ROUTE_SYSTEM:
+ return 1; /* other */
+ case ZEBRA_ROUTE_KERNEL:
+ return 1; /* other */
+ case ZEBRA_ROUTE_CONNECT:
+ return 2; /* local interface */
+ case ZEBRA_ROUTE_STATIC:
+ return 3; /* static route */
+ case ZEBRA_ROUTE_RIP:
+ return 8; /* rip */
+ case ZEBRA_ROUTE_RIPNG:
+ return 1; /* shouldn't happen */
+ case ZEBRA_ROUTE_OSPF:
+ return 13; /* ospf */
+ case ZEBRA_ROUTE_OSPF6:
+ return 1; /* shouldn't happen */
+ case ZEBRA_ROUTE_BGP:
+ return 14; /* bgp */
+ default:
+ return 1; /* other */
+ }
+}
+
+void
+check_replace(struct route_node *np2, struct rib *rib2,
+ struct route_node **np, struct rib **rib)
+{
+ int proto, proto2;
+
+ if (!*np)
+ {
+ *np = np2;
+ *rib = rib2;
+ return;
+ }
+
+ if (in_addr_cmp(&(*np)->p.u.prefix, &np2->p.u.prefix) < 0)
+ return;
+ if (in_addr_cmp(&(*np)->p.u.prefix, &np2->p.u.prefix) > 0)
+ {
+ *np = np2;
+ *rib = rib2;
+ return;
+ }
+
+ proto = proto_trans((*rib)->type);
+ proto2 = proto_trans(rib2->type);
+
+ if (proto2 > proto)
+ return;
+ if (proto2 < proto)
+ {
+ *np = np2;
+ *rib = rib2;
+ return;
+ }
+
+ if (in_addr_cmp((u_char *)&(*rib)->nexthop->gate.ipv4,
+ (u_char *)&rib2->nexthop->gate.ipv4) <= 0)
+ return;
+
+ *np = np2;
+ *rib = rib2;
+ return;
+}
+
+void
+get_fwtable_route_node(struct variable *v, oid objid[], size_t *objid_len,
+ int exact, struct route_node **np, struct rib **rib)
+{
+ struct in_addr dest;
+ struct route_node *np2;
+ struct rib *rib2;
+ int proto;
+ int policy;
+ struct in_addr nexthop;
+ u_char *pnt;
+ int i;
+
+/* Init index variables */
+
+ pnt = (u_char *) &dest;
+ for (i = 0; i < 4; i++)
+ *pnt++ = 0;
+
+ pnt = (u_char *) &nexthop;
+ for (i = 0; i < 4; i++)
+ *pnt++ = 0;
+
+ proto = 0;
+ policy = 0;
+
+/* Init return variables */
+
+ *np = NULL;
+ *rib = NULL;
+
+/* Short circuit exact matches of wrong length */
+
+ if (exact && (*objid_len != v->namelen + 10))
+ return;
+
+/* Get INDEX information out of OID.
+ * ipForwardDest, ipForwardProto, ipForwardPolicy, ipForwardNextHop
+ */
+
+ if (*objid_len > v->namelen)
+ oid2in_addr (objid + v->namelen, MIN(4, *objid_len - v->namelen), &dest);
+
+ if (*objid_len > v->namelen + 4)
+ proto = objid[v->namelen + 4];
+
+ if (*objid_len > v->namelen + 5)
+ policy = objid[v->namelen + 5];
+
+ if (*objid_len > v->namelen + 6)
+ oid2in_addr (objid + v->namelen + 6, MIN(4, *objid_len - v->namelen - 6),
+ &nexthop);
+
+ /* Apply GETNEXT on not exact search */
+
+ if (!exact && (*objid_len >= v->namelen + 10))
+ {
+ if (! in_addr_add((u_char *) &nexthop, 1))
+ return;
+ }
+
+ /* For exact: search matching entry in rib table. */
+
+ if (exact)
+ {
+ if (policy) /* Not supported (yet?) */
+ return;
+ for (*np = route_top (rib_table_ipv4); *np; *np = route_next (*np))
+ {
+ if (!in_addr_cmp(&(*np)->p.u.prefix, (u_char *)&dest))
+ {
+ for (*rib = (*np)->info; *rib; *rib = (*rib)->next)
+ {
+ if (!in_addr_cmp((u_char *)&(*rib)->nexthop->gate.ipv4,
+ (u_char *)&nexthop))
+ if (proto == proto_trans((*rib)->type))
+ return;
+ }
+ }
+ }
+ return;
+ }
+
+/* Search next best entry */
+
+ for (np2 = route_top (rib_table_ipv4); np2; np2 = route_next (np2))
+ {
+
+ /* Check destination first */
+ if (in_addr_cmp(&np2->p.u.prefix, (u_char *)&dest) > 0)
+ for (rib2 = np2->info; rib2; rib2 = rib2->next)
+ check_replace(np2, rib2, np, rib);
+
+ if (in_addr_cmp(&np2->p.u.prefix, (u_char *)&dest) == 0)
+ { /* have to look at each rib individually */
+ for (rib2 = np2->info; rib2; rib2 = rib2->next)
+ {
+ int proto2, policy2;
+
+ proto2 = proto_trans(rib2->type);
+ policy2 = 0;
+
+ if ((policy < policy2)
+ || ((policy == policy2) && (proto < proto2))
+ || ((policy == policy2) && (proto == proto2)
+ && (in_addr_cmp((u_char *)&rib2->nexthop->gate.ipv4,
+ (u_char *) &nexthop) >= 0)
+ ))
+ check_replace(np2, rib2, np, rib);
+ }
+ }
+ }
+
+ if (!*rib)
+ return;
+
+ policy = 0;
+ proto = proto_trans((*rib)->type);
+
+ *objid_len = v->namelen + 10;
+ pnt = (u_char *) &(*np)->p.u.prefix;
+ for (i = 0; i < 4; i++)
+ objid[v->namelen + i] = *pnt++;
+
+ objid[v->namelen + 4] = proto;
+ objid[v->namelen + 5] = policy;
+
+ {
+ struct nexthop *nexthop;
+
+ nexthop = (*rib)->nexthop;
+ if (nexthop)
+ {
+ pnt = (u_char *) &nexthop->gate.ipv4;
+ for (i = 0; i < 4; i++)
+ objid[i + v->namelen + 6] = *pnt++;
+ }
+ }
+
+ return;
+}
+
+u_char *
+ipFwTable (struct variable *v, oid objid[], size_t *objid_len,
+ int exact, size_t *val_len, WriteMethod **write_method)
+{
+ struct route_node *np;
+ struct rib *rib;
+ static int result;
+ static int resarr[2];
+ static struct in_addr netmask;
+ struct nexthop *nexthop;
+
+ get_fwtable_route_node(v, objid, objid_len, exact, &np, &rib);
+ if (!np)
+ return NULL;
+
+ nexthop = rib->nexthop;
+ if (! nexthop)
+ return NULL;
+
+ switch (v->magic)
+ {
+ case IPFORWARDDEST:
+ *val_len = 4;
+ return &np->p.u.prefix;
+ break;
+ case IPFORWARDMASK:
+ masklen2ip(np->p.prefixlen, &netmask);
+ *val_len = 4;
+ return (u_char *)&netmask;
+ break;
+ case IPFORWARDPOLICY:
+ result = 0;
+ *val_len = sizeof(int);
+ return (u_char *)&result;
+ break;
+ case IPFORWARDNEXTHOP:
+ *val_len = 4;
+ return (u_char *)&nexthop->gate.ipv4;
+ break;
+ case IPFORWARDIFINDEX:
+ *val_len = sizeof(int);
+ return (u_char *)&nexthop->ifindex;
+ break;
+ case IPFORWARDTYPE:
+ if (nexthop->type == NEXTHOP_TYPE_IFINDEX
+ || nexthop->type == NEXTHOP_TYPE_IFNAME)
+ result = 3;
+ else
+ result = 4;
+ *val_len = sizeof(int);
+ return (u_char *)&result;
+ break;
+ case IPFORWARDPROTO:
+ result = proto_trans(rib->type);
+ *val_len = sizeof(int);
+ return (u_char *)&result;
+ break;
+ case IPFORWARDAGE:
+ result = 0;
+ *val_len = sizeof(int);
+ return (u_char *)&result;
+ break;
+ case IPFORWARDINFO:
+ resarr[0] = 0;
+ resarr[1] = 0;
+ *val_len = 2 * sizeof(int);
+ return (u_char *)resarr;
+ break;
+ case IPFORWARDNEXTHOPAS:
+ result = -1;
+ *val_len = sizeof(int);
+ return (u_char *)&result;
+ break;
+ case IPFORWARDMETRIC1:
+ result = 0;
+ *val_len = sizeof(int);
+ return (u_char *)&result;
+ break;
+ case IPFORWARDMETRIC2:
+ result = 0;
+ *val_len = sizeof(int);
+ return (u_char *)&result;
+ break;
+ case IPFORWARDMETRIC3:
+ result = 0;
+ *val_len = sizeof(int);
+ return (u_char *)&result;
+ break;
+ case IPFORWARDMETRIC4:
+ result = 0;
+ *val_len = sizeof(int);
+ return (u_char *)&result;
+ break;
+ case IPFORWARDMETRIC5:
+ result = 0;
+ *val_len = sizeof(int);
+ return (u_char *)&result;
+ break;
+ default:
+ return NULL;
+ break;
+ }
+ return NULL;
+}
+
+u_char *
+ipCidrTable (struct variable *v, oid objid[], size_t *objid_len,
+ int exact, size_t *val_len, WriteMethod **write_method)
+{
+ switch (v->magic)
+ {
+ case IPCIDRROUTEDEST:
+ break;
+ default:
+ return NULL;
+ break;
+ }
+ return NULL;
+}
+
+void
+zebra_snmp_init ()
+{
+ smux_init (zebra_oid, sizeof (zebra_oid) / sizeof (oid));
+ REGISTER_MIB("mibII/ipforward", zebra_variables, variable, ipfw_oid);
+ smux_start ();
+}
+#endif /* HAVE_SNMP */