zebra_snmp.c 15 KB

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