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