zebra_snmp.c
上传用户:xiaozhuqw
上传日期:2009-11-15
资源大小:1338k
文件大小:15k
- /* FIB SNMP.
- * 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
- #ifdef HAVE_NETSNMP
- #include <net-snmp/net-snmp-config.h>
- #endif /* HAVE_NETSNMP */
- #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_table *table;
- struct route_node *rn;
- struct rib *rib;
- if (smux_header_generic(v, objid, objid_len, exact, val_len, write_method) == MATCH_FAILED)
- return NULL;
- table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
- if (! table)
- return NULL;
- /* Return number of routing entries. */
- result = 0;
- for (rn = route_top (table); rn; rn = route_next (rn))
- for (rib = rn->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_table *table;
- struct route_node *rn;
- struct rib *rib;
- if (smux_header_generic(v, objid, objid_len, exact, val_len, write_method) == MATCH_FAILED)
- return NULL;
- table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
- if (! table)
- return 0;
- /* Return number of routing entries. */
- result = 0;
- for (rn = route_top (table); rn; rn = route_next (rn))
- for (rib = rn->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_table *table;
- 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;
- table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
- if (! table)
- 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 (table); *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 (table); 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 */