rip_snmp.c 14 KB

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