rip_snmp.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594
  1. /* RIP SNMP support
  2. * Copyright (C) 1999 Kunihiro Ishiguro <kunihiro@zebra.org>
  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 "table.h"
  30. #include "smux.h"
  31. #include "ripd/ripd.h"
  32. /* RIPv2-MIB. */
  33. #define RIPV2MIB 1,3,6,1,2,1,23
  34. /* RIPv2-MIB rip2Globals values. */
  35. #define RIP2GLOBALROUTECHANGES 1
  36. #define RIP2GLOBALQUERIES 2
  37. /* RIPv2-MIB rip2IfStatEntry. */
  38. #define RIP2IFSTATENTRY 1
  39. /* RIPv2-MIB rip2IfStatTable. */
  40. #define RIP2IFSTATADDRESS 1
  41. #define RIP2IFSTATRCVBADPACKETS 2
  42. #define RIP2IFSTATRCVBADROUTES 3
  43. #define RIP2IFSTATSENTUPDATES 4
  44. #define RIP2IFSTATSTATUS 5
  45. /* RIPv2-MIB rip2IfConfTable. */
  46. #define RIP2IFCONFADDRESS 1
  47. #define RIP2IFCONFDOMAIN 2
  48. #define RIP2IFCONFAUTHTYPE 3
  49. #define RIP2IFCONFAUTHKEY 4
  50. #define RIP2IFCONFSEND 5
  51. #define RIP2IFCONFRECEIVE 6
  52. #define RIP2IFCONFDEFAULTMETRIC 7
  53. #define RIP2IFCONFSTATUS 8
  54. #define RIP2IFCONFSRCADDRESS 9
  55. /* RIPv2-MIB rip2PeerTable. */
  56. #define RIP2PEERADDRESS 1
  57. #define RIP2PEERDOMAIN 2
  58. #define RIP2PEERLASTUPDATE 3
  59. #define RIP2PEERVERSION 4
  60. #define RIP2PEERRCVBADPACKETS 5
  61. #define RIP2PEERRCVBADROUTES 6
  62. /* SNMP value hack. */
  63. #define COUNTER ASN_COUNTER
  64. #define INTEGER ASN_INTEGER
  65. #define TIMETICKS ASN_TIMETICKS
  66. #define IPADDRESS ASN_IPADDRESS
  67. #define STRING ASN_OCTET_STR
  68. /* Define SNMP local variables. */
  69. SNMP_LOCAL_VARIABLES
  70. /* RIP-MIB instances. */
  71. oid rip_oid [] = { RIPV2MIB };
  72. /* Interface cache table sorted by interface's address. */
  73. struct route_table *rip_ifaddr_table;
  74. /* Hook functions. */
  75. static u_char *rip2Globals (struct variable *, oid [], size_t *,
  76. int, size_t *, WriteMethod **);
  77. static u_char *rip2IfStatEntry (struct variable *, oid [], size_t *,
  78. int, size_t *, WriteMethod **);
  79. static u_char *rip2IfConfAddress (struct variable *, oid [], size_t *,
  80. int, size_t *, WriteMethod **);
  81. static u_char *rip2PeerTable (struct variable *, oid [], size_t *,
  82. int, size_t *, WriteMethod **);
  83. struct variable rip_variables[] =
  84. {
  85. /* RIP Global Counters. */
  86. {RIP2GLOBALROUTECHANGES, COUNTER, RONLY, rip2Globals,
  87. 2, {1, 1}},
  88. {RIP2GLOBALQUERIES, COUNTER, RONLY, rip2Globals,
  89. 2, {1, 2}},
  90. /* RIP Interface Tables. */
  91. {RIP2IFSTATADDRESS, IPADDRESS, RONLY, rip2IfStatEntry,
  92. 3, {2, 1, 1}},
  93. {RIP2IFSTATRCVBADPACKETS, COUNTER, RONLY, rip2IfStatEntry,
  94. 3, {2, 1, 2}},
  95. {RIP2IFSTATRCVBADROUTES, COUNTER, RONLY, rip2IfStatEntry,
  96. 3, {2, 1, 3}},
  97. {RIP2IFSTATSENTUPDATES, COUNTER, RONLY, rip2IfStatEntry,
  98. 3, {2, 1, 4}},
  99. {RIP2IFSTATSTATUS, COUNTER, RWRITE, rip2IfStatEntry,
  100. 3, {2, 1, 5}},
  101. {RIP2IFCONFADDRESS, IPADDRESS, RONLY, rip2IfConfAddress,
  102. /* RIP Interface Configuration Table. */
  103. 3, {3, 1, 1}},
  104. {RIP2IFCONFDOMAIN, STRING, RONLY, rip2IfConfAddress,
  105. 3, {3, 1, 2}},
  106. {RIP2IFCONFAUTHTYPE, COUNTER, RONLY, rip2IfConfAddress,
  107. 3, {3, 1, 3}},
  108. {RIP2IFCONFAUTHKEY, STRING, RONLY, rip2IfConfAddress,
  109. 3, {3, 1, 4}},
  110. {RIP2IFCONFSEND, COUNTER, RONLY, rip2IfConfAddress,
  111. 3, {3, 1, 5}},
  112. {RIP2IFCONFRECEIVE, COUNTER, RONLY, rip2IfConfAddress,
  113. 3, {3, 1, 6}},
  114. {RIP2IFCONFDEFAULTMETRIC, COUNTER, RONLY, rip2IfConfAddress,
  115. 3, {3, 1, 7}},
  116. {RIP2IFCONFSTATUS, COUNTER, RONLY, rip2IfConfAddress,
  117. 3, {3, 1, 8}},
  118. {RIP2IFCONFSRCADDRESS, IPADDRESS, RONLY, rip2IfConfAddress,
  119. 3, {3, 1, 9}},
  120. {RIP2PEERADDRESS, IPADDRESS, RONLY, rip2PeerTable,
  121. /* RIP Peer Table. */
  122. 3, {4, 1, 1}},
  123. {RIP2PEERDOMAIN, STRING, RONLY, rip2PeerTable,
  124. 3, {4, 1, 2}},
  125. {RIP2PEERLASTUPDATE, TIMETICKS, RONLY, rip2PeerTable,
  126. 3, {4, 1, 3}},
  127. {RIP2PEERVERSION, INTEGER, RONLY, rip2PeerTable,
  128. 3, {4, 1, 4}},
  129. {RIP2PEERRCVBADPACKETS, COUNTER, RONLY, rip2PeerTable,
  130. 3, {4, 1, 5}},
  131. {RIP2PEERRCVBADROUTES, COUNTER, RONLY, rip2PeerTable,
  132. 3, {4, 1, 6}}
  133. };
  134. extern struct thread_master *master;
  135. static u_char *
  136. rip2Globals (struct variable *v, oid name[], size_t *length,
  137. int exact, size_t *var_len, WriteMethod **write_method)
  138. {
  139. if (smux_header_generic(v, name, length, exact, var_len, write_method)
  140. == MATCH_FAILED)
  141. return NULL;
  142. /* Retrun global counter. */
  143. switch (v->magic)
  144. {
  145. case RIP2GLOBALROUTECHANGES:
  146. return SNMP_INTEGER (rip_global_route_changes);
  147. break;
  148. case RIP2GLOBALQUERIES:
  149. return SNMP_INTEGER (rip_global_queries);
  150. break;
  151. default:
  152. return NULL;
  153. break;
  154. }
  155. return NULL;
  156. }
  157. void
  158. rip_ifaddr_add (struct interface *ifp, struct connected *ifc)
  159. {
  160. struct prefix *p;
  161. struct route_node *rn;
  162. p = ifc->address;
  163. if (p->family != AF_INET)
  164. return;
  165. rn = route_node_get (rip_ifaddr_table, p);
  166. rn->info = ifp;
  167. }
  168. void
  169. rip_ifaddr_delete (struct interface *ifp, struct connected *ifc)
  170. {
  171. struct prefix *p;
  172. struct route_node *rn;
  173. struct interface *i;
  174. p = ifc->address;
  175. if (p->family != AF_INET)
  176. return;
  177. rn = route_node_lookup (rip_ifaddr_table, p);
  178. if (! rn)
  179. return;
  180. i = rn->info;
  181. if (rn && !strncmp(i->name,ifp->name,INTERFACE_NAMSIZ))
  182. {
  183. rn->info = NULL;
  184. route_unlock_node (rn);
  185. route_unlock_node (rn);
  186. }
  187. }
  188. static struct interface *
  189. rip_ifaddr_lookup_next (struct in_addr *addr)
  190. {
  191. struct prefix_ipv4 p;
  192. struct route_node *rn;
  193. struct interface *ifp;
  194. p.family = AF_INET;
  195. p.prefixlen = IPV4_MAX_BITLEN;
  196. p.prefix = *addr;
  197. rn = route_node_get (rip_ifaddr_table, (struct prefix *) &p);
  198. for (rn = route_next (rn); rn; rn = route_next (rn))
  199. if (rn->info)
  200. break;
  201. if (rn && rn->info)
  202. {
  203. ifp = rn->info;
  204. *addr = rn->p.u.prefix4;
  205. route_unlock_node (rn);
  206. return ifp;
  207. }
  208. return NULL;
  209. }
  210. static struct interface *
  211. rip2IfLookup (struct variable *v, oid name[], size_t *length,
  212. struct in_addr *addr, int exact)
  213. {
  214. int len;
  215. struct interface *ifp;
  216. if (exact)
  217. {
  218. /* Check the length. */
  219. if (*length - v->namelen != sizeof (struct in_addr))
  220. return NULL;
  221. oid2in_addr (name + v->namelen, sizeof (struct in_addr), addr);
  222. return if_lookup_exact_address (*addr);
  223. }
  224. else
  225. {
  226. len = *length - v->namelen;
  227. if (len > 4) len = 4;
  228. oid2in_addr (name + v->namelen, len, addr);
  229. ifp = rip_ifaddr_lookup_next (addr);
  230. if (ifp == NULL)
  231. return NULL;
  232. oid_copy_addr (name + v->namelen, addr, sizeof (struct in_addr));
  233. *length = v->namelen + sizeof (struct in_addr);
  234. return ifp;
  235. }
  236. return NULL;
  237. }
  238. static struct rip_peer *
  239. rip2PeerLookup (struct variable *v, oid name[], size_t *length,
  240. struct in_addr *addr, int exact)
  241. {
  242. int len;
  243. struct rip_peer *peer;
  244. if (exact)
  245. {
  246. /* Check the length. */
  247. if (*length - v->namelen != sizeof (struct in_addr) + 1)
  248. return NULL;
  249. oid2in_addr (name + v->namelen, sizeof (struct in_addr), addr);
  250. peer = rip_peer_lookup (addr);
  251. if (peer->domain == (int)name[v->namelen + sizeof (struct in_addr)])
  252. return peer;
  253. return NULL;
  254. }
  255. else
  256. {
  257. len = *length - v->namelen;
  258. if (len > 4) len = 4;
  259. oid2in_addr (name + v->namelen, len, addr);
  260. len = *length - v->namelen;
  261. peer = rip_peer_lookup (addr);
  262. if (peer)
  263. {
  264. if ((len < (int)sizeof (struct in_addr) + 1) ||
  265. (peer->domain > (int)name[v->namelen + sizeof (struct in_addr)]))
  266. {
  267. oid_copy_addr (name + v->namelen, &peer->addr,
  268. sizeof (struct in_addr));
  269. name[v->namelen + sizeof (struct in_addr)] = peer->domain;
  270. *length = sizeof (struct in_addr) + v->namelen + 1;
  271. return peer;
  272. }
  273. }
  274. peer = rip_peer_lookup_next (addr);
  275. if (! peer)
  276. return NULL;
  277. oid_copy_addr (name + v->namelen, &peer->addr,
  278. sizeof (struct in_addr));
  279. name[v->namelen + sizeof (struct in_addr)] = peer->domain;
  280. *length = sizeof (struct in_addr) + v->namelen + 1;
  281. return peer;
  282. }
  283. return NULL;
  284. }
  285. static u_char *
  286. rip2IfStatEntry (struct variable *v, oid name[], size_t *length,
  287. int exact, size_t *var_len, WriteMethod **write_method)
  288. {
  289. struct interface *ifp;
  290. struct rip_interface *ri;
  291. static struct in_addr addr;
  292. static long valid = SNMP_VALID;
  293. if (smux_header_table(v, name, length, exact, var_len, write_method)
  294. == MATCH_FAILED)
  295. return NULL;
  296. memset (&addr, 0, sizeof (struct in_addr));
  297. /* Lookup interface. */
  298. ifp = rip2IfLookup (v, name, length, &addr, exact);
  299. if (! ifp)
  300. return NULL;
  301. /* Fetch rip_interface information. */
  302. ri = ifp->info;
  303. switch (v->magic)
  304. {
  305. case RIP2IFSTATADDRESS:
  306. return SNMP_IPADDRESS (addr);
  307. break;
  308. case RIP2IFSTATRCVBADPACKETS:
  309. *var_len = sizeof (long);
  310. return (u_char *) &ri->recv_badpackets;
  311. case RIP2IFSTATRCVBADROUTES:
  312. *var_len = sizeof (long);
  313. return (u_char *) &ri->recv_badroutes;
  314. case RIP2IFSTATSENTUPDATES:
  315. *var_len = sizeof (long);
  316. return (u_char *) &ri->sent_updates;
  317. case RIP2IFSTATSTATUS:
  318. *var_len = sizeof (long);
  319. v->type = ASN_INTEGER;
  320. return (u_char *) &valid;
  321. default:
  322. return NULL;
  323. }
  324. return NULL;
  325. }
  326. static long
  327. rip2IfConfSend (struct rip_interface *ri)
  328. {
  329. #define doNotSend 1
  330. #define ripVersion1 2
  331. #define rip1Compatible 3
  332. #define ripVersion2 4
  333. #define ripV1Demand 5
  334. #define ripV2Demand 6
  335. if (! ri->running)
  336. return doNotSend;
  337. if (ri->ri_send & RIPv2)
  338. return ripVersion2;
  339. else if (ri->ri_send & RIPv1)
  340. return ripVersion1;
  341. else if (rip)
  342. {
  343. if (rip->version_send == RIPv2)
  344. return ripVersion2;
  345. else if (rip->version_send == RIPv1)
  346. return ripVersion1;
  347. }
  348. return doNotSend;
  349. }
  350. static long
  351. rip2IfConfReceive (struct rip_interface *ri)
  352. {
  353. #define rip1 1
  354. #define rip2 2
  355. #define rip1OrRip2 3
  356. #define doNotReceive 4
  357. int recvv;
  358. if (! ri->running)
  359. return doNotReceive;
  360. recvv = (ri->ri_receive == RI_RIP_UNSPEC) ? rip->version_recv :
  361. ri->ri_receive;
  362. if (recvv == RI_RIP_VERSION_1_AND_2)
  363. return rip1OrRip2;
  364. else if (recvv & RIPv2)
  365. return rip2;
  366. else if (recvv & RIPv1)
  367. return rip1;
  368. else
  369. return doNotReceive;
  370. }
  371. static u_char *
  372. rip2IfConfAddress (struct variable *v, oid name[], size_t *length,
  373. int exact, size_t *val_len, WriteMethod **write_method)
  374. {
  375. static struct in_addr addr;
  376. static long valid = SNMP_INVALID;
  377. static long domain = 0;
  378. static long config = 0;
  379. static u_int auth = 0;
  380. struct interface *ifp;
  381. struct rip_interface *ri;
  382. if (smux_header_table(v, name, length, exact, val_len, write_method)
  383. == MATCH_FAILED)
  384. return NULL;
  385. memset (&addr, 0, sizeof (struct in_addr));
  386. /* Lookup interface. */
  387. ifp = rip2IfLookup (v, name, length, &addr, exact);
  388. if (! ifp)
  389. return NULL;
  390. /* Fetch rip_interface information. */
  391. ri = ifp->info;
  392. switch (v->magic)
  393. {
  394. case RIP2IFCONFADDRESS:
  395. *val_len = sizeof (struct in_addr);
  396. return (u_char *) &addr;
  397. case RIP2IFCONFDOMAIN:
  398. *val_len = 2;
  399. return (u_char *) &domain;
  400. case RIP2IFCONFAUTHTYPE:
  401. auth = ri->auth_type;
  402. *val_len = sizeof (long);
  403. v->type = ASN_INTEGER;
  404. return (u_char *)&auth;
  405. case RIP2IFCONFAUTHKEY:
  406. *val_len = 0;
  407. return (u_char *) &domain;
  408. case RIP2IFCONFSEND:
  409. config = rip2IfConfSend (ri);
  410. *val_len = sizeof (long);
  411. v->type = ASN_INTEGER;
  412. return (u_char *) &config;
  413. case RIP2IFCONFRECEIVE:
  414. config = rip2IfConfReceive (ri);
  415. *val_len = sizeof (long);
  416. v->type = ASN_INTEGER;
  417. return (u_char *) &config;
  418. case RIP2IFCONFDEFAULTMETRIC:
  419. *val_len = sizeof (long);
  420. v->type = ASN_INTEGER;
  421. return (u_char *) &ifp->metric;
  422. case RIP2IFCONFSTATUS:
  423. *val_len = sizeof (long);
  424. v->type = ASN_INTEGER;
  425. return (u_char *) &valid;
  426. case RIP2IFCONFSRCADDRESS:
  427. *val_len = sizeof (struct in_addr);
  428. return (u_char *) &addr;
  429. default:
  430. return NULL;
  431. }
  432. return NULL;
  433. }
  434. static u_char *
  435. rip2PeerTable (struct variable *v, oid name[], size_t *length,
  436. int exact, size_t *val_len, WriteMethod **write_method)
  437. {
  438. static struct in_addr addr;
  439. static int domain = 0;
  440. static int version;
  441. /* static time_t uptime; */
  442. struct rip_peer *peer;
  443. if (smux_header_table(v, name, length, exact, val_len, write_method)
  444. == MATCH_FAILED)
  445. return NULL;
  446. memset (&addr, 0, sizeof (struct in_addr));
  447. /* Lookup interface. */
  448. peer = rip2PeerLookup (v, name, length, &addr, exact);
  449. if (! peer)
  450. return NULL;
  451. switch (v->magic)
  452. {
  453. case RIP2PEERADDRESS:
  454. *val_len = sizeof (struct in_addr);
  455. return (u_char *) &peer->addr;
  456. case RIP2PEERDOMAIN:
  457. *val_len = 2;
  458. return (u_char *) &domain;
  459. case RIP2PEERLASTUPDATE:
  460. #if 0
  461. /* We don't know the SNMP agent startup time. We have two choices here:
  462. * - assume ripd startup time equals SNMP agent startup time
  463. * - don't support this variable, at all
  464. * Currently, we do the latter...
  465. */
  466. *val_len = sizeof (time_t);
  467. uptime = peer->uptime; /* now - snmp_agent_startup - peer->uptime */
  468. return (u_char *) &uptime;
  469. #else
  470. return (u_char *) NULL;
  471. #endif
  472. case RIP2PEERVERSION:
  473. *val_len = sizeof (int);
  474. version = peer->version;
  475. return (u_char *) &version;
  476. case RIP2PEERRCVBADPACKETS:
  477. *val_len = sizeof (int);
  478. return (u_char *) &peer->recv_badpackets;
  479. case RIP2PEERRCVBADROUTES:
  480. *val_len = sizeof (int);
  481. return (u_char *) &peer->recv_badroutes;
  482. default:
  483. return NULL;
  484. }
  485. return NULL;
  486. }
  487. /* Register RIPv2-MIB. */
  488. void
  489. rip_snmp_init ()
  490. {
  491. rip_ifaddr_table = route_table_init ();
  492. smux_init (master);
  493. REGISTER_MIB("mibII/rip", rip_variables, variable, rip_oid);
  494. }
  495. #endif /* HAVE_SNMP */