rip_snmp.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581
  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. #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 "table.h"
  34. #include "smux.h"
  35. #include "ripd/ripd.h"
  36. /* RIPv2-MIB. */
  37. #define RIPV2MIB 1,3,6,1,2,1,23
  38. /* RIPv2-MIB rip2Globals values. */
  39. #define RIP2GLOBALROUTECHANGES 1
  40. #define RIP2GLOBALQUERIES 2
  41. /* RIPv2-MIB rip2IfStatEntry. */
  42. #define RIP2IFSTATENTRY 1
  43. /* RIPv2-MIB rip2IfStatTable. */
  44. #define RIP2IFSTATADDRESS 1
  45. #define RIP2IFSTATRCVBADPACKETS 2
  46. #define RIP2IFSTATRCVBADROUTES 3
  47. #define RIP2IFSTATSENTUPDATES 4
  48. #define RIP2IFSTATSTATUS 5
  49. /* RIPv2-MIB rip2IfConfTable. */
  50. #define RIP2IFCONFADDRESS 1
  51. #define RIP2IFCONFDOMAIN 2
  52. #define RIP2IFCONFAUTHTYPE 3
  53. #define RIP2IFCONFAUTHKEY 4
  54. #define RIP2IFCONFSEND 5
  55. #define RIP2IFCONFRECEIVE 6
  56. #define RIP2IFCONFDEFAULTMETRIC 7
  57. #define RIP2IFCONFSTATUS 8
  58. #define RIP2IFCONFSRCADDRESS 9
  59. /* RIPv2-MIB rip2PeerTable. */
  60. #define RIP2PEERADDRESS 1
  61. #define RIP2PEERDOMAIN 2
  62. #define RIP2PEERLASTUPDATE 3
  63. #define RIP2PEERVERSION 4
  64. #define RIP2PEERRCVBADPACKETS 5
  65. #define RIP2PEERRCVBADROUTES 6
  66. /* SNMP value hack. */
  67. #define COUNTER ASN_COUNTER
  68. #define INTEGER ASN_INTEGER
  69. #define TIMETICKS ASN_TIMETICKS
  70. #define IPADDRESS ASN_IPADDRESS
  71. #define STRING ASN_OCTET_STR
  72. /* Define SNMP local variables. */
  73. SNMP_LOCAL_VARIABLES
  74. /* RIP-MIB instances. */
  75. oid rip_oid [] = { RIPV2MIB };
  76. /* Interface cache table sorted by interface's address. */
  77. struct route_table *rip_ifaddr_table;
  78. /* Hook functions. */
  79. static u_char *rip2Globals ();
  80. static u_char *rip2IfStatEntry ();
  81. static u_char *rip2IfConfAddress ();
  82. static u_char *rip2PeerTable ();
  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. 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 == 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 < sizeof (struct in_addr) + 1) ||
  265. (peer->domain > 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. memset (&addr, 0, sizeof (struct in_addr));
  294. /* Lookup interface. */
  295. ifp = rip2IfLookup (v, name, length, &addr, exact);
  296. if (! ifp)
  297. return NULL;
  298. /* Fetch rip_interface information. */
  299. ri = ifp->info;
  300. switch (v->magic)
  301. {
  302. case RIP2IFSTATADDRESS:
  303. return SNMP_IPADDRESS (addr);
  304. break;
  305. case RIP2IFSTATRCVBADPACKETS:
  306. *var_len = sizeof (long);
  307. return (u_char *) &ri->recv_badpackets;
  308. case RIP2IFSTATRCVBADROUTES:
  309. *var_len = sizeof (long);
  310. return (u_char *) &ri->recv_badroutes;
  311. case RIP2IFSTATSENTUPDATES:
  312. *var_len = sizeof (long);
  313. return (u_char *) &ri->sent_updates;
  314. case RIP2IFSTATSTATUS:
  315. *var_len = sizeof (long);
  316. v->type = ASN_INTEGER;
  317. return (u_char *) &valid;
  318. default:
  319. return NULL;
  320. }
  321. return NULL;
  322. }
  323. static long
  324. rip2IfConfSend (struct rip_interface *ri)
  325. {
  326. #define doNotSend 1
  327. #define ripVersion1 2
  328. #define rip1Compatible 3
  329. #define ripVersion2 4
  330. #define ripV1Demand 5
  331. #define ripV2Demand 6
  332. if (! ri->running)
  333. return doNotSend;
  334. if (ri->ri_send & RIPv2)
  335. return ripVersion2;
  336. else if (ri->ri_send & RIPv1)
  337. return ripVersion1;
  338. else if (rip)
  339. {
  340. if (rip->version_send == RIPv2)
  341. return ripVersion2;
  342. else if (rip->version_send == RIPv1)
  343. return ripVersion1;
  344. }
  345. return doNotSend;
  346. }
  347. static long
  348. rip2IfConfReceive (struct rip_interface *ri)
  349. {
  350. #define rip1 1
  351. #define rip2 2
  352. #define rip1OrRip2 3
  353. #define doNotReceive 4
  354. int recvv;
  355. if (! ri->running)
  356. return doNotReceive;
  357. recvv = (ri->ri_receive == RI_RIP_UNSPEC) ? rip->version_recv :
  358. ri->ri_receive;
  359. if (recvv == RI_RIP_VERSION_1_AND_2)
  360. return rip1OrRip2;
  361. else if (recvv & RIPv2)
  362. return rip2;
  363. else if (recvv & RIPv1)
  364. return rip1;
  365. else
  366. return doNotReceive;
  367. }
  368. static u_char *
  369. rip2IfConfAddress (struct variable *v, oid name[], size_t *length,
  370. int exact, size_t *val_len, WriteMethod **write_method)
  371. {
  372. static struct in_addr addr;
  373. static long valid = SNMP_INVALID;
  374. static long domain = 0;
  375. static long config = 0;
  376. static u_int auth = 0;
  377. struct interface *ifp;
  378. struct rip_interface *ri;
  379. memset (&addr, 0, sizeof (struct in_addr));
  380. /* Lookup interface. */
  381. ifp = rip2IfLookup (v, name, length, &addr, exact);
  382. if (! ifp)
  383. return NULL;
  384. /* Fetch rip_interface information. */
  385. ri = ifp->info;
  386. switch (v->magic)
  387. {
  388. case RIP2IFCONFADDRESS:
  389. *val_len = sizeof (struct in_addr);
  390. return (u_char *) &addr;
  391. case RIP2IFCONFDOMAIN:
  392. *val_len = 2;
  393. return (u_char *) &domain;
  394. case RIP2IFCONFAUTHTYPE:
  395. auth = ri->auth_type;
  396. *val_len = sizeof (long);
  397. v->type = ASN_INTEGER;
  398. return (u_char *)&auth;
  399. case RIP2IFCONFAUTHKEY:
  400. *val_len = 0;
  401. return (u_char *) &domain;
  402. case RIP2IFCONFSEND:
  403. config = rip2IfConfSend (ri);
  404. *val_len = sizeof (long);
  405. v->type = ASN_INTEGER;
  406. return (u_char *) &config;
  407. case RIP2IFCONFRECEIVE:
  408. config = rip2IfConfReceive (ri);
  409. *val_len = sizeof (long);
  410. v->type = ASN_INTEGER;
  411. return (u_char *) &config;
  412. case RIP2IFCONFDEFAULTMETRIC:
  413. *val_len = sizeof (long);
  414. v->type = ASN_INTEGER;
  415. return (u_char *) &ifp->metric;
  416. case RIP2IFCONFSTATUS:
  417. *val_len = sizeof (long);
  418. v->type = ASN_INTEGER;
  419. return (u_char *) &valid;
  420. case RIP2IFCONFSRCADDRESS:
  421. *val_len = sizeof (struct in_addr);
  422. return (u_char *) &addr;
  423. default:
  424. return NULL;
  425. }
  426. return NULL;
  427. }
  428. static u_char *
  429. rip2PeerTable (struct variable *v, oid name[], size_t *length,
  430. int exact, size_t *val_len, WriteMethod **write_method)
  431. {
  432. static struct in_addr addr;
  433. static int domain = 0;
  434. static int version;
  435. /* static time_t uptime; */
  436. struct rip_peer *peer;
  437. memset (&addr, 0, sizeof (struct in_addr));
  438. /* Lookup interface. */
  439. peer = rip2PeerLookup (v, name, length, &addr, exact);
  440. if (! peer)
  441. return NULL;
  442. switch (v->magic)
  443. {
  444. case RIP2PEERADDRESS:
  445. *val_len = sizeof (struct in_addr);
  446. return (u_char *) &peer->addr;
  447. case RIP2PEERDOMAIN:
  448. *val_len = 2;
  449. return (u_char *) &domain;
  450. case RIP2PEERLASTUPDATE:
  451. #if 0
  452. /* We don't know the SNMP agent startup time. We have two choices here:
  453. * - assume ripd startup time equals SNMP agent startup time
  454. * - don't support this variable, at all
  455. * Currently, we do the latter...
  456. */
  457. *val_len = sizeof (time_t);
  458. uptime = peer->uptime; /* now - snmp_agent_startup - peer->uptime */
  459. return (u_char *) &uptime;
  460. #else
  461. return (u_char *) NULL;
  462. #endif
  463. case RIP2PEERVERSION:
  464. *val_len = sizeof (int);
  465. version = peer->version;
  466. return (u_char *) &version;
  467. case RIP2PEERRCVBADPACKETS:
  468. *val_len = sizeof (int);
  469. return (u_char *) &peer->recv_badpackets;
  470. case RIP2PEERRCVBADROUTES:
  471. *val_len = sizeof (int);
  472. return (u_char *) &peer->recv_badroutes;
  473. default:
  474. return NULL;
  475. }
  476. return NULL;
  477. }
  478. /* Register RIPv2-MIB. */
  479. void
  480. rip_snmp_init ()
  481. {
  482. rip_ifaddr_table = route_table_init ();
  483. smux_init (master);
  484. REGISTER_MIB("mibII/rip", rip_variables, variable, rip_oid);
  485. }
  486. #endif /* HAVE_SNMP */