zebra_snmp.c 15 KB

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