zebra_snmp.c 15 KB

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