zebra_snmp.c 15 KB

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