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