Annotation of embedaddon/quagga/zebra/zebra_snmp.c, revision 1.1
1.1 ! misho 1: /* FIB SNMP.
! 2: * Copyright (C) 1999 Kunihiro Ishiguro
! 3: *
! 4: * This file is part of GNU Zebra.
! 5: *
! 6: * GNU Zebra is free software; you can redistribute it and/or modify it
! 7: * under the terms of the GNU General Public License as published by the
! 8: * Free Software Foundation; either version 2, or (at your option) any
! 9: * later version.
! 10: *
! 11: * GNU Zebra is distributed in the hope that it will be useful, but
! 12: * WITHOUT ANY WARRANTY; without even the implied warranty of
! 13: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
! 14: * General Public License for more details.
! 15: *
! 16: * You should have received a copy of the GNU General Public License
! 17: * along with GNU Zebra; see the file COPYING. If not, write to the Free
! 18: * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
! 19: * 02111-1307, USA.
! 20: */
! 21:
! 22: #include <zebra.h>
! 23:
! 24: #ifdef HAVE_SNMP
! 25: #ifdef HAVE_NETSNMP
! 26: #include <net-snmp/net-snmp-config.h>
! 27: #include <net-snmp/net-snmp-includes.h>
! 28: #else
! 29: #include <asn1.h>
! 30: #include <snmp.h>
! 31: #include <snmp_impl.h>
! 32: #endif
! 33:
! 34: #include "if.h"
! 35: #include "log.h"
! 36: #include "prefix.h"
! 37: #include "command.h"
! 38: #include "smux.h"
! 39: #include "table.h"
! 40:
! 41: #include "zebra/rib.h"
! 42: #include "zebra/zserv.h"
! 43:
! 44: #define IPFWMIB 1,3,6,1,2,1,4,24
! 45:
! 46: /* ipForwardTable */
! 47: #define IPFORWARDDEST 1
! 48: #define IPFORWARDMASK 2
! 49: #define IPFORWARDPOLICY 3
! 50: #define IPFORWARDNEXTHOP 4
! 51: #define IPFORWARDIFINDEX 5
! 52: #define IPFORWARDTYPE 6
! 53: #define IPFORWARDPROTO 7
! 54: #define IPFORWARDAGE 8
! 55: #define IPFORWARDINFO 9
! 56: #define IPFORWARDNEXTHOPAS 10
! 57: #define IPFORWARDMETRIC1 11
! 58: #define IPFORWARDMETRIC2 12
! 59: #define IPFORWARDMETRIC3 13
! 60: #define IPFORWARDMETRIC4 14
! 61: #define IPFORWARDMETRIC5 15
! 62:
! 63: /* ipCidrRouteTable */
! 64: #define IPCIDRROUTEDEST 1
! 65: #define IPCIDRROUTEMASK 2
! 66: #define IPCIDRROUTETOS 3
! 67: #define IPCIDRROUTENEXTHOP 4
! 68: #define IPCIDRROUTEIFINDEX 5
! 69: #define IPCIDRROUTETYPE 6
! 70: #define IPCIDRROUTEPROTO 7
! 71: #define IPCIDRROUTEAGE 8
! 72: #define IPCIDRROUTEINFO 9
! 73: #define IPCIDRROUTENEXTHOPAS 10
! 74: #define IPCIDRROUTEMETRIC1 11
! 75: #define IPCIDRROUTEMETRIC2 12
! 76: #define IPCIDRROUTEMETRIC3 13
! 77: #define IPCIDRROUTEMETRIC4 14
! 78: #define IPCIDRROUTEMETRIC5 15
! 79: #define IPCIDRROUTESTATUS 16
! 80:
! 81: #define INTEGER32 ASN_INTEGER
! 82: #define GAUGE32 ASN_GAUGE
! 83: #define ENUMERATION ASN_INTEGER
! 84: #define ROWSTATUS ASN_INTEGER
! 85: #define IPADDRESS ASN_IPADDRESS
! 86: #define OBJECTIDENTIFIER ASN_OBJECT_ID
! 87:
! 88: extern struct zebra_t zebrad;
! 89:
! 90: oid ipfw_oid [] = { IPFWMIB };
! 91:
! 92: /* Hook functions. */
! 93: static u_char * ipFwNumber (struct variable *, oid [], size_t *,
! 94: int, size_t *, WriteMethod **);
! 95: static u_char * ipFwTable (struct variable *, oid [], size_t *,
! 96: int, size_t *, WriteMethod **);
! 97: static u_char * ipCidrNumber (struct variable *, oid [], size_t *,
! 98: int, size_t *, WriteMethod **);
! 99: static u_char * ipCidrTable (struct variable *, oid [], size_t *,
! 100: int, size_t *, WriteMethod **);
! 101:
! 102: struct variable zebra_variables[] =
! 103: {
! 104: {0, GAUGE32, RONLY, ipFwNumber, 1, {1}},
! 105: {IPFORWARDDEST, IPADDRESS, RONLY, ipFwTable, 3, {2, 1, 1}},
! 106: {IPFORWARDMASK, IPADDRESS, RONLY, ipFwTable, 3, {2, 1, 2}},
! 107: {IPFORWARDPOLICY, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 3}},
! 108: {IPFORWARDNEXTHOP, IPADDRESS, RONLY, ipFwTable, 3, {2, 1, 4}},
! 109: {IPFORWARDIFINDEX, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 5}},
! 110: {IPFORWARDTYPE, ENUMERATION, RONLY, ipFwTable, 3, {2, 1, 6}},
! 111: {IPFORWARDPROTO, ENUMERATION, RONLY, ipFwTable, 3, {2, 1, 7}},
! 112: {IPFORWARDAGE, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 8}},
! 113: {IPFORWARDINFO, OBJECTIDENTIFIER, RONLY, ipFwTable, 3, {2, 1, 9}},
! 114: {IPFORWARDNEXTHOPAS, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 10}},
! 115: {IPFORWARDMETRIC1, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 11}},
! 116: {IPFORWARDMETRIC2, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 12}},
! 117: {IPFORWARDMETRIC3, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 13}},
! 118: {IPFORWARDMETRIC4, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 14}},
! 119: {IPFORWARDMETRIC5, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 15}},
! 120: {0, GAUGE32, RONLY, ipCidrNumber, 1, {3}},
! 121: {IPCIDRROUTEDEST, IPADDRESS, RONLY, ipCidrTable, 3, {4, 1, 1}},
! 122: {IPCIDRROUTEMASK, IPADDRESS, RONLY, ipCidrTable, 3, {4, 1, 2}},
! 123: {IPCIDRROUTETOS, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 3}},
! 124: {IPCIDRROUTENEXTHOP, IPADDRESS, RONLY, ipCidrTable, 3, {4, 1, 4}},
! 125: {IPCIDRROUTEIFINDEX, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 5}},
! 126: {IPCIDRROUTETYPE, ENUMERATION, RONLY, ipCidrTable, 3, {4, 1, 6}},
! 127: {IPCIDRROUTEPROTO, ENUMERATION, RONLY, ipCidrTable, 3, {4, 1, 7}},
! 128: {IPCIDRROUTEAGE, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 8}},
! 129: {IPCIDRROUTEINFO, OBJECTIDENTIFIER, RONLY, ipCidrTable, 3, {4, 1, 9}},
! 130: {IPCIDRROUTENEXTHOPAS, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 10}},
! 131: {IPCIDRROUTEMETRIC1, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 11}},
! 132: {IPCIDRROUTEMETRIC2, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 12}},
! 133: {IPCIDRROUTEMETRIC3, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 13}},
! 134: {IPCIDRROUTEMETRIC4, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 14}},
! 135: {IPCIDRROUTEMETRIC5, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 15}},
! 136: {IPCIDRROUTESTATUS, ROWSTATUS, RONLY, ipCidrTable, 3, {4, 1, 16}}
! 137: };
! 138:
! 139:
! 140: static u_char *
! 141: ipFwNumber (struct variable *v, oid objid[], size_t *objid_len,
! 142: int exact, size_t *val_len, WriteMethod **write_method)
! 143: {
! 144: static int result;
! 145: struct route_table *table;
! 146: struct route_node *rn;
! 147: struct rib *rib;
! 148:
! 149: if (smux_header_generic(v, objid, objid_len, exact, val_len, write_method) == MATCH_FAILED)
! 150: return NULL;
! 151:
! 152: table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
! 153: if (! table)
! 154: return NULL;
! 155:
! 156: /* Return number of routing entries. */
! 157: result = 0;
! 158: for (rn = route_top (table); rn; rn = route_next (rn))
! 159: for (rib = rn->info; rib; rib = rib->next)
! 160: result++;
! 161:
! 162: return (u_char *)&result;
! 163: }
! 164:
! 165: static u_char *
! 166: ipCidrNumber (struct variable *v, oid objid[], size_t *objid_len,
! 167: int exact, size_t *val_len, WriteMethod **write_method)
! 168: {
! 169: static int result;
! 170: struct route_table *table;
! 171: struct route_node *rn;
! 172: struct rib *rib;
! 173:
! 174: if (smux_header_generic(v, objid, objid_len, exact, val_len, write_method) == MATCH_FAILED)
! 175: return NULL;
! 176:
! 177: table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
! 178: if (! table)
! 179: return 0;
! 180:
! 181: /* Return number of routing entries. */
! 182: result = 0;
! 183: for (rn = route_top (table); rn; rn = route_next (rn))
! 184: for (rib = rn->info; rib; rib = rib->next)
! 185: result++;
! 186:
! 187: return (u_char *)&result;
! 188: }
! 189:
! 190: static int
! 191: in_addr_cmp(u_char *p1, u_char *p2)
! 192: {
! 193: int i;
! 194:
! 195: for (i=0; i<4; i++)
! 196: {
! 197: if (*p1 < *p2)
! 198: return -1;
! 199: if (*p1 > *p2)
! 200: return 1;
! 201: p1++; p2++;
! 202: }
! 203: return 0;
! 204: }
! 205:
! 206: static int
! 207: in_addr_add(u_char *p, int num)
! 208: {
! 209: int i, ip0;
! 210:
! 211: ip0 = *p;
! 212: p += 4;
! 213: for (i = 3; 0 <= i; i--) {
! 214: p--;
! 215: if (*p + num > 255) {
! 216: *p += num;
! 217: num = 1;
! 218: } else {
! 219: *p += num;
! 220: return 1;
! 221: }
! 222: }
! 223: if (ip0 > *p) {
! 224: /* ip + num > 0xffffffff */
! 225: return 0;
! 226: }
! 227:
! 228: return 1;
! 229: }
! 230:
! 231: static int
! 232: proto_trans(int type)
! 233: {
! 234: switch (type)
! 235: {
! 236: case ZEBRA_ROUTE_SYSTEM:
! 237: return 1; /* other */
! 238: case ZEBRA_ROUTE_KERNEL:
! 239: return 1; /* other */
! 240: case ZEBRA_ROUTE_CONNECT:
! 241: return 2; /* local interface */
! 242: case ZEBRA_ROUTE_STATIC:
! 243: return 3; /* static route */
! 244: case ZEBRA_ROUTE_RIP:
! 245: return 8; /* rip */
! 246: case ZEBRA_ROUTE_RIPNG:
! 247: return 1; /* shouldn't happen */
! 248: case ZEBRA_ROUTE_OSPF:
! 249: return 13; /* ospf */
! 250: case ZEBRA_ROUTE_OSPF6:
! 251: return 1; /* shouldn't happen */
! 252: case ZEBRA_ROUTE_BGP:
! 253: return 14; /* bgp */
! 254: default:
! 255: return 1; /* other */
! 256: }
! 257: }
! 258:
! 259: static void
! 260: check_replace(struct route_node *np2, struct rib *rib2,
! 261: struct route_node **np, struct rib **rib)
! 262: {
! 263: int proto, proto2;
! 264:
! 265: if (!*np)
! 266: {
! 267: *np = np2;
! 268: *rib = rib2;
! 269: return;
! 270: }
! 271:
! 272: if (in_addr_cmp(&(*np)->p.u.prefix, &np2->p.u.prefix) < 0)
! 273: return;
! 274: if (in_addr_cmp(&(*np)->p.u.prefix, &np2->p.u.prefix) > 0)
! 275: {
! 276: *np = np2;
! 277: *rib = rib2;
! 278: return;
! 279: }
! 280:
! 281: proto = proto_trans((*rib)->type);
! 282: proto2 = proto_trans(rib2->type);
! 283:
! 284: if (proto2 > proto)
! 285: return;
! 286: if (proto2 < proto)
! 287: {
! 288: *np = np2;
! 289: *rib = rib2;
! 290: return;
! 291: }
! 292:
! 293: if (in_addr_cmp((u_char *)&(*rib)->nexthop->gate.ipv4,
! 294: (u_char *)&rib2->nexthop->gate.ipv4) <= 0)
! 295: return;
! 296:
! 297: *np = np2;
! 298: *rib = rib2;
! 299: return;
! 300: }
! 301:
! 302: static void
! 303: get_fwtable_route_node(struct variable *v, oid objid[], size_t *objid_len,
! 304: int exact, struct route_node **np, struct rib **rib)
! 305: {
! 306: struct in_addr dest;
! 307: struct route_table *table;
! 308: struct route_node *np2;
! 309: struct rib *rib2;
! 310: int proto;
! 311: int policy;
! 312: struct in_addr nexthop;
! 313: u_char *pnt;
! 314: int i;
! 315:
! 316: /* Init index variables */
! 317:
! 318: pnt = (u_char *) &dest;
! 319: for (i = 0; i < 4; i++)
! 320: *pnt++ = 0;
! 321:
! 322: pnt = (u_char *) &nexthop;
! 323: for (i = 0; i < 4; i++)
! 324: *pnt++ = 0;
! 325:
! 326: proto = 0;
! 327: policy = 0;
! 328:
! 329: /* Init return variables */
! 330:
! 331: *np = NULL;
! 332: *rib = NULL;
! 333:
! 334: /* Short circuit exact matches of wrong length */
! 335:
! 336: if (exact && (*objid_len != (unsigned) v->namelen + 10))
! 337: return;
! 338:
! 339: table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
! 340: if (! table)
! 341: return;
! 342:
! 343: /* Get INDEX information out of OID.
! 344: * ipForwardDest, ipForwardProto, ipForwardPolicy, ipForwardNextHop
! 345: */
! 346:
! 347: if (*objid_len > (unsigned) v->namelen)
! 348: oid2in_addr (objid + v->namelen, MIN(4, *objid_len - v->namelen), &dest);
! 349:
! 350: if (*objid_len > (unsigned) v->namelen + 4)
! 351: proto = objid[v->namelen + 4];
! 352:
! 353: if (*objid_len > (unsigned) v->namelen + 5)
! 354: policy = objid[v->namelen + 5];
! 355:
! 356: if (*objid_len > (unsigned) v->namelen + 6)
! 357: oid2in_addr (objid + v->namelen + 6, MIN(4, *objid_len - v->namelen - 6),
! 358: &nexthop);
! 359:
! 360: /* Apply GETNEXT on not exact search */
! 361:
! 362: if (!exact && (*objid_len >= (unsigned) v->namelen + 10))
! 363: {
! 364: if (! in_addr_add((u_char *) &nexthop, 1))
! 365: return;
! 366: }
! 367:
! 368: /* For exact: search matching entry in rib table. */
! 369:
! 370: if (exact)
! 371: {
! 372: if (policy) /* Not supported (yet?) */
! 373: return;
! 374: for (*np = route_top (table); *np; *np = route_next (*np))
! 375: {
! 376: if (!in_addr_cmp(&(*np)->p.u.prefix, (u_char *)&dest))
! 377: {
! 378: for (*rib = (*np)->info; *rib; *rib = (*rib)->next)
! 379: {
! 380: if (!in_addr_cmp((u_char *)&(*rib)->nexthop->gate.ipv4,
! 381: (u_char *)&nexthop))
! 382: if (proto == proto_trans((*rib)->type))
! 383: return;
! 384: }
! 385: }
! 386: }
! 387: return;
! 388: }
! 389:
! 390: /* Search next best entry */
! 391:
! 392: for (np2 = route_top (table); np2; np2 = route_next (np2))
! 393: {
! 394:
! 395: /* Check destination first */
! 396: if (in_addr_cmp(&np2->p.u.prefix, (u_char *)&dest) > 0)
! 397: for (rib2 = np2->info; rib2; rib2 = rib2->next)
! 398: check_replace(np2, rib2, np, rib);
! 399:
! 400: if (in_addr_cmp(&np2->p.u.prefix, (u_char *)&dest) == 0)
! 401: { /* have to look at each rib individually */
! 402: for (rib2 = np2->info; rib2; rib2 = rib2->next)
! 403: {
! 404: int proto2, policy2;
! 405:
! 406: proto2 = proto_trans(rib2->type);
! 407: policy2 = 0;
! 408:
! 409: if ((policy < policy2)
! 410: || ((policy == policy2) && (proto < proto2))
! 411: || ((policy == policy2) && (proto == proto2)
! 412: && (in_addr_cmp((u_char *)&rib2->nexthop->gate.ipv4,
! 413: (u_char *) &nexthop) >= 0)
! 414: ))
! 415: check_replace(np2, rib2, np, rib);
! 416: }
! 417: }
! 418: }
! 419:
! 420: if (!*rib)
! 421: return;
! 422:
! 423: policy = 0;
! 424: proto = proto_trans((*rib)->type);
! 425:
! 426: *objid_len = v->namelen + 10;
! 427: pnt = (u_char *) &(*np)->p.u.prefix;
! 428: for (i = 0; i < 4; i++)
! 429: objid[v->namelen + i] = *pnt++;
! 430:
! 431: objid[v->namelen + 4] = proto;
! 432: objid[v->namelen + 5] = policy;
! 433:
! 434: {
! 435: struct nexthop *nexthop;
! 436:
! 437: nexthop = (*rib)->nexthop;
! 438: if (nexthop)
! 439: {
! 440: pnt = (u_char *) &nexthop->gate.ipv4;
! 441: for (i = 0; i < 4; i++)
! 442: objid[i + v->namelen + 6] = *pnt++;
! 443: }
! 444: }
! 445:
! 446: return;
! 447: }
! 448:
! 449: static u_char *
! 450: ipFwTable (struct variable *v, oid objid[], size_t *objid_len,
! 451: int exact, size_t *val_len, WriteMethod **write_method)
! 452: {
! 453: struct route_node *np;
! 454: struct rib *rib;
! 455: static int result;
! 456: static int resarr[2];
! 457: static struct in_addr netmask;
! 458: struct nexthop *nexthop;
! 459:
! 460: get_fwtable_route_node(v, objid, objid_len, exact, &np, &rib);
! 461: if (!np)
! 462: return NULL;
! 463:
! 464: nexthop = rib->nexthop;
! 465: if (! nexthop)
! 466: return NULL;
! 467:
! 468: switch (v->magic)
! 469: {
! 470: case IPFORWARDDEST:
! 471: *val_len = 4;
! 472: return &np->p.u.prefix;
! 473: break;
! 474: case IPFORWARDMASK:
! 475: masklen2ip(np->p.prefixlen, &netmask);
! 476: *val_len = 4;
! 477: return (u_char *)&netmask;
! 478: break;
! 479: case IPFORWARDPOLICY:
! 480: result = 0;
! 481: *val_len = sizeof(int);
! 482: return (u_char *)&result;
! 483: break;
! 484: case IPFORWARDNEXTHOP:
! 485: *val_len = 4;
! 486: return (u_char *)&nexthop->gate.ipv4;
! 487: break;
! 488: case IPFORWARDIFINDEX:
! 489: *val_len = sizeof(int);
! 490: return (u_char *)&nexthop->ifindex;
! 491: break;
! 492: case IPFORWARDTYPE:
! 493: if (nexthop->type == NEXTHOP_TYPE_IFINDEX
! 494: || nexthop->type == NEXTHOP_TYPE_IFNAME)
! 495: result = 3;
! 496: else
! 497: result = 4;
! 498: *val_len = sizeof(int);
! 499: return (u_char *)&result;
! 500: break;
! 501: case IPFORWARDPROTO:
! 502: result = proto_trans(rib->type);
! 503: *val_len = sizeof(int);
! 504: return (u_char *)&result;
! 505: break;
! 506: case IPFORWARDAGE:
! 507: result = 0;
! 508: *val_len = sizeof(int);
! 509: return (u_char *)&result;
! 510: break;
! 511: case IPFORWARDINFO:
! 512: resarr[0] = 0;
! 513: resarr[1] = 0;
! 514: *val_len = 2 * sizeof(int);
! 515: return (u_char *)resarr;
! 516: break;
! 517: case IPFORWARDNEXTHOPAS:
! 518: result = -1;
! 519: *val_len = sizeof(int);
! 520: return (u_char *)&result;
! 521: break;
! 522: case IPFORWARDMETRIC1:
! 523: result = 0;
! 524: *val_len = sizeof(int);
! 525: return (u_char *)&result;
! 526: break;
! 527: case IPFORWARDMETRIC2:
! 528: result = 0;
! 529: *val_len = sizeof(int);
! 530: return (u_char *)&result;
! 531: break;
! 532: case IPFORWARDMETRIC3:
! 533: result = 0;
! 534: *val_len = sizeof(int);
! 535: return (u_char *)&result;
! 536: break;
! 537: case IPFORWARDMETRIC4:
! 538: result = 0;
! 539: *val_len = sizeof(int);
! 540: return (u_char *)&result;
! 541: break;
! 542: case IPFORWARDMETRIC5:
! 543: result = 0;
! 544: *val_len = sizeof(int);
! 545: return (u_char *)&result;
! 546: break;
! 547: default:
! 548: return NULL;
! 549: break;
! 550: }
! 551: return NULL;
! 552: }
! 553:
! 554: static u_char *
! 555: ipCidrTable (struct variable *v, oid objid[], size_t *objid_len,
! 556: int exact, size_t *val_len, WriteMethod **write_method)
! 557: {
! 558: switch (v->magic)
! 559: {
! 560: case IPCIDRROUTEDEST:
! 561: break;
! 562: default:
! 563: return NULL;
! 564: break;
! 565: }
! 566: return NULL;
! 567: }
! 568:
! 569: void
! 570: zebra_snmp_init ()
! 571: {
! 572: smux_init (zebrad.master);
! 573: REGISTER_MIB("mibII/ipforward", zebra_variables, variable, ipfw_oid);
! 574: }
! 575: #endif /* HAVE_SNMP */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>