ripng_interface.c 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212
  1. /*
  2. * Interface related function for RIPng.
  3. * Copyright (C) 1998 Kunihiro Ishiguro
  4. *
  5. * This file is part of GNU Zebra.
  6. *
  7. * GNU Zebra is free software; you can redistribute it and/or modify it
  8. * under the terms of the GNU General Public License as published by the
  9. * Free Software Foundation; either version 2, or (at your option) any
  10. * later version.
  11. *
  12. * GNU Zebra is distributed in the hope that it will be useful, but
  13. * WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with GNU Zebra; see the file COPYING. If not, write to the Free
  19. * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
  20. * 02111-1307, USA.
  21. */
  22. #include <zebra.h>
  23. #include "linklist.h"
  24. #include "if.h"
  25. #include "prefix.h"
  26. #include "memory.h"
  27. #include "network.h"
  28. #include "filter.h"
  29. #include "log.h"
  30. #include "stream.h"
  31. #include "zclient.h"
  32. #include "command.h"
  33. #include "table.h"
  34. #include "thread.h"
  35. #include "privs.h"
  36. #include "ripngd/ripngd.h"
  37. #include "ripngd/ripng_debug.h"
  38. /* If RFC2133 definition is used. */
  39. #ifndef IPV6_JOIN_GROUP
  40. #define IPV6_JOIN_GROUP IPV6_ADD_MEMBERSHIP
  41. #endif
  42. #ifndef IPV6_LEAVE_GROUP
  43. #define IPV6_LEAVE_GROUP IPV6_DROP_MEMBERSHIP
  44. #endif
  45. extern struct zebra_privs_t ripngd_privs;
  46. /* Static utility function. */
  47. static void ripng_enable_apply (struct interface *);
  48. static void ripng_passive_interface_apply (struct interface *);
  49. static int ripng_enable_if_lookup (const char *);
  50. static int ripng_enable_network_lookup2 (struct connected *);
  51. static void ripng_enable_apply_all (void);
  52. /* Join to the all rip routers multicast group. */
  53. static int
  54. ripng_multicast_join (struct interface *ifp)
  55. {
  56. int ret;
  57. struct ipv6_mreq mreq;
  58. int save_errno;
  59. if (if_is_up (ifp) && if_is_multicast (ifp)) {
  60. memset (&mreq, 0, sizeof (mreq));
  61. inet_pton(AF_INET6, RIPNG_GROUP, &mreq.ipv6mr_multiaddr);
  62. mreq.ipv6mr_interface = ifp->ifindex;
  63. /*
  64. * NetBSD 1.6.2 requires root to join groups on gif(4).
  65. * While this is bogus, privs are available and easy to use
  66. * for this call as a workaround.
  67. */
  68. if (ripngd_privs.change (ZPRIVS_RAISE))
  69. zlog_err ("ripng_multicast_join: could not raise privs");
  70. ret = setsockopt (ripng->sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
  71. (char *) &mreq, sizeof (mreq));
  72. save_errno = errno;
  73. if (ripngd_privs.change (ZPRIVS_LOWER))
  74. zlog_err ("ripng_multicast_join: could not lower privs");
  75. if (ret < 0 && save_errno == EADDRINUSE)
  76. {
  77. /*
  78. * Group is already joined. This occurs due to sloppy group
  79. * management, in particular declining to leave the group on
  80. * an interface that has just gone down.
  81. */
  82. zlog_warn ("ripng join on %s EADDRINUSE (ignoring)\n", ifp->name);
  83. return 0; /* not an error */
  84. }
  85. if (ret < 0)
  86. zlog_warn ("can't setsockopt IPV6_JOIN_GROUP: %s",
  87. safe_strerror (save_errno));
  88. if (IS_RIPNG_DEBUG_EVENT)
  89. zlog_debug ("RIPng %s join to all-rip-routers multicast group", ifp->name);
  90. if (ret < 0)
  91. return -1;
  92. }
  93. return 0;
  94. }
  95. /* Leave from the all rip routers multicast group. */
  96. static int
  97. ripng_multicast_leave (struct interface *ifp)
  98. {
  99. int ret;
  100. struct ipv6_mreq mreq;
  101. if (if_is_up (ifp) && if_is_multicast (ifp)) {
  102. memset (&mreq, 0, sizeof (mreq));
  103. inet_pton(AF_INET6, RIPNG_GROUP, &mreq.ipv6mr_multiaddr);
  104. mreq.ipv6mr_interface = ifp->ifindex;
  105. ret = setsockopt (ripng->sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
  106. (char *) &mreq, sizeof (mreq));
  107. if (ret < 0)
  108. zlog_warn ("can't setsockopt IPV6_LEAVE_GROUP: %s\n", safe_strerror (errno));
  109. if (IS_RIPNG_DEBUG_EVENT)
  110. zlog_debug ("RIPng %s leave from all-rip-routers multicast group",
  111. ifp->name);
  112. if (ret < 0)
  113. return -1;
  114. }
  115. return 0;
  116. }
  117. /* How many link local IPv6 address could be used on the interface ? */
  118. static int
  119. ripng_if_ipv6_lladdress_check (struct interface *ifp)
  120. {
  121. struct listnode *nn;
  122. struct connected *connected;
  123. int count = 0;
  124. for (ALL_LIST_ELEMENTS_RO (ifp->connected, nn, connected))
  125. {
  126. struct prefix *p;
  127. p = connected->address;
  128. if ((p->family == AF_INET6) &&
  129. IN6_IS_ADDR_LINKLOCAL (&p->u.prefix6))
  130. count++;
  131. }
  132. return count;
  133. }
  134. static int
  135. ripng_if_down (struct interface *ifp)
  136. {
  137. struct route_node *rp;
  138. struct ripng_info *rinfo;
  139. struct ripng_interface *ri;
  140. struct list *list = NULL;
  141. struct listnode *listnode = NULL, *nextnode = NULL;
  142. if (ripng)
  143. for (rp = route_top (ripng->table); rp; rp = route_next (rp))
  144. if ((list = rp->info) != NULL)
  145. for (ALL_LIST_ELEMENTS (list, listnode, nextnode, rinfo))
  146. if (rinfo->ifindex == ifp->ifindex)
  147. ripng_ecmp_delete (rinfo);
  148. ri = ifp->info;
  149. if (ri->running)
  150. {
  151. if (IS_RIPNG_DEBUG_EVENT)
  152. zlog_debug ("turn off %s", ifp->name);
  153. /* Leave from multicast group. */
  154. ripng_multicast_leave (ifp);
  155. ri->running = 0;
  156. }
  157. return 0;
  158. }
  159. /* Inteface link up message processing. */
  160. int
  161. ripng_interface_up (int command, struct zclient *zclient, zebra_size_t length)
  162. {
  163. struct stream *s;
  164. struct interface *ifp;
  165. /* zebra_interface_state_read() updates interface structure in iflist. */
  166. s = zclient->ibuf;
  167. ifp = zebra_interface_state_read (s);
  168. if (ifp == NULL)
  169. return 0;
  170. if (IS_RIPNG_DEBUG_ZEBRA)
  171. zlog_debug ("interface up %s index %d flags %llx metric %d mtu %d",
  172. ifp->name, ifp->ifindex, (unsigned long long)ifp->flags,
  173. ifp->metric, ifp->mtu6);
  174. /* Check if this interface is RIPng enabled or not. */
  175. ripng_enable_apply (ifp);
  176. /* Check for a passive interface. */
  177. ripng_passive_interface_apply (ifp);
  178. /* Apply distribute list to the all interface. */
  179. ripng_distribute_update_interface (ifp);
  180. return 0;
  181. }
  182. /* Inteface link down message processing. */
  183. int
  184. ripng_interface_down (int command, struct zclient *zclient,
  185. zebra_size_t length)
  186. {
  187. struct stream *s;
  188. struct interface *ifp;
  189. /* zebra_interface_state_read() updates interface structure in iflist. */
  190. s = zclient->ibuf;
  191. ifp = zebra_interface_state_read (s);
  192. if (ifp == NULL)
  193. return 0;
  194. ripng_if_down (ifp);
  195. if (IS_RIPNG_DEBUG_ZEBRA)
  196. zlog_debug ("interface down %s index %d flags %#llx metric %d mtu %d",
  197. ifp->name, ifp->ifindex,
  198. (unsigned long long) ifp->flags, ifp->metric, ifp->mtu6);
  199. return 0;
  200. }
  201. /* Inteface addition message from zebra. */
  202. int
  203. ripng_interface_add (int command, struct zclient *zclient, zebra_size_t length)
  204. {
  205. struct interface *ifp;
  206. ifp = zebra_interface_add_read (zclient->ibuf);
  207. if (IS_RIPNG_DEBUG_ZEBRA)
  208. zlog_debug ("RIPng interface add %s index %d flags %#llx metric %d mtu %d",
  209. ifp->name, ifp->ifindex, (unsigned long long) ifp->flags,
  210. ifp->metric, ifp->mtu6);
  211. /* Check is this interface is RIP enabled or not.*/
  212. ripng_enable_apply (ifp);
  213. /* Apply distribute list to the interface. */
  214. ripng_distribute_update_interface (ifp);
  215. /* Check interface routemap. */
  216. ripng_if_rmap_update_interface (ifp);
  217. return 0;
  218. }
  219. int
  220. ripng_interface_delete (int command, struct zclient *zclient,
  221. zebra_size_t length)
  222. {
  223. struct interface *ifp;
  224. struct stream *s;
  225. s = zclient->ibuf;
  226. /* zebra_interface_state_read() updates interface structure in iflist */
  227. ifp = zebra_interface_state_read(s);
  228. if (ifp == NULL)
  229. return 0;
  230. if (if_is_up (ifp)) {
  231. ripng_if_down(ifp);
  232. }
  233. zlog_info("interface delete %s index %d flags %#llx metric %d mtu %d",
  234. ifp->name, ifp->ifindex, (unsigned long long) ifp->flags,
  235. ifp->metric, ifp->mtu6);
  236. /* To support pseudo interface do not free interface structure. */
  237. /* if_delete(ifp); */
  238. ifp->ifindex = IFINDEX_INTERNAL;
  239. return 0;
  240. }
  241. void
  242. ripng_interface_clean (void)
  243. {
  244. struct listnode *node, *nnode;
  245. struct interface *ifp;
  246. struct ripng_interface *ri;
  247. for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp))
  248. {
  249. ri = ifp->info;
  250. ri->enable_network = 0;
  251. ri->enable_interface = 0;
  252. ri->running = 0;
  253. if (ri->t_wakeup)
  254. {
  255. thread_cancel (ri->t_wakeup);
  256. ri->t_wakeup = NULL;
  257. }
  258. }
  259. }
  260. void
  261. ripng_interface_reset (void)
  262. {
  263. struct listnode *node;
  264. struct interface *ifp;
  265. struct ripng_interface *ri;
  266. for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
  267. {
  268. ri = ifp->info;
  269. ri->enable_network = 0;
  270. ri->enable_interface = 0;
  271. ri->running = 0;
  272. ri->split_horizon = RIPNG_NO_SPLIT_HORIZON;
  273. ri->split_horizon_default = RIPNG_NO_SPLIT_HORIZON;
  274. ri->list[RIPNG_FILTER_IN] = NULL;
  275. ri->list[RIPNG_FILTER_OUT] = NULL;
  276. ri->prefix[RIPNG_FILTER_IN] = NULL;
  277. ri->prefix[RIPNG_FILTER_OUT] = NULL;
  278. if (ri->t_wakeup)
  279. {
  280. thread_cancel (ri->t_wakeup);
  281. ri->t_wakeup = NULL;
  282. }
  283. ri->passive = 0;
  284. }
  285. }
  286. static void
  287. ripng_apply_address_add (struct connected *ifc) {
  288. struct prefix_ipv6 address;
  289. struct prefix *p;
  290. if (!ripng)
  291. return;
  292. if (! if_is_up(ifc->ifp))
  293. return;
  294. p = ifc->address;
  295. memset (&address, 0, sizeof (address));
  296. address.family = p->family;
  297. address.prefix = p->u.prefix6;
  298. address.prefixlen = p->prefixlen;
  299. apply_mask_ipv6(&address);
  300. /* Check if this interface is RIP enabled or not
  301. or Check if this address's prefix is RIP enabled */
  302. if ((ripng_enable_if_lookup(ifc->ifp->name) >= 0) ||
  303. (ripng_enable_network_lookup2(ifc) >= 0))
  304. ripng_redistribute_add(ZEBRA_ROUTE_CONNECT, RIPNG_ROUTE_INTERFACE,
  305. &address, ifc->ifp->ifindex, NULL);
  306. }
  307. int
  308. ripng_interface_address_add (int command, struct zclient *zclient,
  309. zebra_size_t length)
  310. {
  311. struct connected *c;
  312. struct prefix *p;
  313. c = zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_ADD,
  314. zclient->ibuf);
  315. if (c == NULL)
  316. return 0;
  317. p = c->address;
  318. if (p->family == AF_INET6)
  319. {
  320. struct ripng_interface *ri = c->ifp->info;
  321. if (IS_RIPNG_DEBUG_ZEBRA)
  322. zlog_debug ("RIPng connected address %s/%d add",
  323. inet6_ntoa(p->u.prefix6),
  324. p->prefixlen);
  325. /* Check is this prefix needs to be redistributed. */
  326. ripng_apply_address_add(c);
  327. /* Let's try once again whether the interface could be activated */
  328. if (!ri->running) {
  329. /* Check if this interface is RIP enabled or not.*/
  330. ripng_enable_apply (c->ifp);
  331. /* Apply distribute list to the interface. */
  332. ripng_distribute_update_interface (c->ifp);
  333. /* Check interface routemap. */
  334. ripng_if_rmap_update_interface (c->ifp);
  335. }
  336. }
  337. return 0;
  338. }
  339. static void
  340. ripng_apply_address_del (struct connected *ifc) {
  341. struct prefix_ipv6 address;
  342. struct prefix *p;
  343. if (!ripng)
  344. return;
  345. if (! if_is_up(ifc->ifp))
  346. return;
  347. p = ifc->address;
  348. memset (&address, 0, sizeof (address));
  349. address.family = p->family;
  350. address.prefix = p->u.prefix6;
  351. address.prefixlen = p->prefixlen;
  352. apply_mask_ipv6(&address);
  353. ripng_redistribute_delete(ZEBRA_ROUTE_CONNECT, RIPNG_ROUTE_INTERFACE,
  354. &address, ifc->ifp->ifindex);
  355. }
  356. int
  357. ripng_interface_address_delete (int command, struct zclient *zclient,
  358. zebra_size_t length)
  359. {
  360. struct connected *ifc;
  361. struct prefix *p;
  362. char buf[INET6_ADDRSTRLEN];
  363. ifc = zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_DELETE,
  364. zclient->ibuf);
  365. if (ifc)
  366. {
  367. p = ifc->address;
  368. if (p->family == AF_INET6)
  369. {
  370. if (IS_RIPNG_DEBUG_ZEBRA)
  371. zlog_debug ("RIPng connected address %s/%d delete",
  372. inet_ntop (AF_INET6, &p->u.prefix6, buf,
  373. INET6_ADDRSTRLEN),
  374. p->prefixlen);
  375. /* Check wether this prefix needs to be removed. */
  376. ripng_apply_address_del(ifc);
  377. }
  378. connected_free (ifc);
  379. }
  380. return 0;
  381. }
  382. /* RIPng enable interface vector. */
  383. vector ripng_enable_if;
  384. /* RIPng enable network table. */
  385. struct route_table *ripng_enable_network;
  386. /* Lookup RIPng enable network. */
  387. /* Check wether the interface has at least a connected prefix that
  388. * is within the ripng_enable_network table. */
  389. static int
  390. ripng_enable_network_lookup_if (struct interface *ifp)
  391. {
  392. struct listnode *node;
  393. struct connected *connected;
  394. struct prefix_ipv6 address;
  395. for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, connected))
  396. {
  397. struct prefix *p;
  398. struct route_node *node;
  399. p = connected->address;
  400. if (p->family == AF_INET6)
  401. {
  402. address.family = AF_INET6;
  403. address.prefix = p->u.prefix6;
  404. address.prefixlen = IPV6_MAX_BITLEN;
  405. node = route_node_match (ripng_enable_network,
  406. (struct prefix *)&address);
  407. if (node)
  408. {
  409. route_unlock_node (node);
  410. return 1;
  411. }
  412. }
  413. }
  414. return -1;
  415. }
  416. /* Check wether connected is within the ripng_enable_network table. */
  417. static int
  418. ripng_enable_network_lookup2 (struct connected *connected)
  419. {
  420. struct prefix_ipv6 address;
  421. struct prefix *p;
  422. p = connected->address;
  423. if (p->family == AF_INET6) {
  424. struct route_node *node;
  425. address.family = p->family;
  426. address.prefix = p->u.prefix6;
  427. address.prefixlen = IPV6_MAX_BITLEN;
  428. /* LPM on p->family, p->u.prefix6/IPV6_MAX_BITLEN within ripng_enable_network */
  429. node = route_node_match (ripng_enable_network,
  430. (struct prefix *)&address);
  431. if (node) {
  432. route_unlock_node (node);
  433. return 1;
  434. }
  435. }
  436. return -1;
  437. }
  438. /* Add RIPng enable network. */
  439. static int
  440. ripng_enable_network_add (struct prefix *p)
  441. {
  442. struct route_node *node;
  443. node = route_node_get (ripng_enable_network, p);
  444. if (node->info)
  445. {
  446. route_unlock_node (node);
  447. return -1;
  448. }
  449. else
  450. node->info = (char *) "enabled";
  451. /* XXX: One should find a better solution than a generic one */
  452. ripng_enable_apply_all();
  453. return 1;
  454. }
  455. /* Delete RIPng enable network. */
  456. static int
  457. ripng_enable_network_delete (struct prefix *p)
  458. {
  459. struct route_node *node;
  460. node = route_node_lookup (ripng_enable_network, p);
  461. if (node)
  462. {
  463. node->info = NULL;
  464. /* Unlock info lock. */
  465. route_unlock_node (node);
  466. /* Unlock lookup lock. */
  467. route_unlock_node (node);
  468. return 1;
  469. }
  470. return -1;
  471. }
  472. /* Lookup function. */
  473. static int
  474. ripng_enable_if_lookup (const char *ifname)
  475. {
  476. unsigned int i;
  477. char *str;
  478. for (i = 0; i < vector_active (ripng_enable_if); i++)
  479. if ((str = vector_slot (ripng_enable_if, i)) != NULL)
  480. if (strcmp (str, ifname) == 0)
  481. return i;
  482. return -1;
  483. }
  484. /* Add interface to ripng_enable_if. */
  485. static int
  486. ripng_enable_if_add (const char *ifname)
  487. {
  488. int ret;
  489. ret = ripng_enable_if_lookup (ifname);
  490. if (ret >= 0)
  491. return -1;
  492. vector_set (ripng_enable_if, strdup (ifname));
  493. ripng_enable_apply_all();
  494. return 1;
  495. }
  496. /* Delete interface from ripng_enable_if. */
  497. static int
  498. ripng_enable_if_delete (const char *ifname)
  499. {
  500. int index;
  501. char *str;
  502. index = ripng_enable_if_lookup (ifname);
  503. if (index < 0)
  504. return -1;
  505. str = vector_slot (ripng_enable_if, index);
  506. free (str);
  507. vector_unset (ripng_enable_if, index);
  508. ripng_enable_apply_all();
  509. return 1;
  510. }
  511. /* Wake up interface. */
  512. static int
  513. ripng_interface_wakeup (struct thread *t)
  514. {
  515. struct interface *ifp;
  516. struct ripng_interface *ri;
  517. /* Get interface. */
  518. ifp = THREAD_ARG (t);
  519. ri = ifp->info;
  520. ri->t_wakeup = NULL;
  521. /* Join to multicast group. */
  522. if (ripng_multicast_join (ifp) < 0) {
  523. zlog_err ("multicast join failed, interface %s not running", ifp->name);
  524. return 0;
  525. }
  526. /* Set running flag. */
  527. ri->running = 1;
  528. /* Send RIP request to the interface. */
  529. ripng_request (ifp);
  530. return 0;
  531. }
  532. static void
  533. ripng_connect_set (struct interface *ifp, int set)
  534. {
  535. struct listnode *node, *nnode;
  536. struct connected *connected;
  537. struct prefix_ipv6 address;
  538. for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, connected))
  539. {
  540. struct prefix *p;
  541. p = connected->address;
  542. if (p->family != AF_INET6)
  543. continue;
  544. address.family = AF_INET6;
  545. address.prefix = p->u.prefix6;
  546. address.prefixlen = p->prefixlen;
  547. apply_mask_ipv6 (&address);
  548. if (set) {
  549. /* Check once more wether this prefix is within a "network IF_OR_PREF" one */
  550. if ((ripng_enable_if_lookup(connected->ifp->name) >= 0) ||
  551. (ripng_enable_network_lookup2(connected) >= 0))
  552. ripng_redistribute_add (ZEBRA_ROUTE_CONNECT, RIPNG_ROUTE_INTERFACE,
  553. &address, connected->ifp->ifindex, NULL);
  554. } else {
  555. ripng_redistribute_delete (ZEBRA_ROUTE_CONNECT, RIPNG_ROUTE_INTERFACE,
  556. &address, connected->ifp->ifindex);
  557. if (ripng_redistribute_check (ZEBRA_ROUTE_CONNECT))
  558. ripng_redistribute_add (ZEBRA_ROUTE_CONNECT, RIPNG_ROUTE_REDISTRIBUTE,
  559. &address, connected->ifp->ifindex, NULL);
  560. }
  561. }
  562. }
  563. /* Check RIPng is enabed on this interface. */
  564. void
  565. ripng_enable_apply (struct interface *ifp)
  566. {
  567. int ret;
  568. struct ripng_interface *ri = NULL;
  569. /* Check interface. */
  570. if (! if_is_up (ifp))
  571. return;
  572. ri = ifp->info;
  573. /* Is this interface a candidate for RIPng ? */
  574. ret = ripng_enable_network_lookup_if (ifp);
  575. /* If the interface is matched. */
  576. if (ret > 0)
  577. ri->enable_network = 1;
  578. else
  579. ri->enable_network = 0;
  580. /* Check interface name configuration. */
  581. ret = ripng_enable_if_lookup (ifp->name);
  582. if (ret >= 0)
  583. ri->enable_interface = 1;
  584. else
  585. ri->enable_interface = 0;
  586. /* any candidate interface MUST have a link-local IPv6 address */
  587. if ((! ripng_if_ipv6_lladdress_check (ifp)) &&
  588. (ri->enable_network || ri->enable_interface)) {
  589. ri->enable_network = 0;
  590. ri->enable_interface = 0;
  591. zlog_warn("Interface %s does not have any link-local address",
  592. ifp->name);
  593. }
  594. /* Update running status of the interface. */
  595. if (ri->enable_network || ri->enable_interface)
  596. {
  597. {
  598. if (IS_RIPNG_DEBUG_EVENT)
  599. zlog_debug ("RIPng turn on %s", ifp->name);
  600. /* Add interface wake up thread. */
  601. if (! ri->t_wakeup)
  602. ri->t_wakeup = thread_add_timer (master, ripng_interface_wakeup,
  603. ifp, 1);
  604. ripng_connect_set (ifp, 1);
  605. }
  606. }
  607. else
  608. {
  609. if (ri->running)
  610. {
  611. /* Might as well clean up the route table as well
  612. * ripng_if_down sets to 0 ri->running, and displays "turn off %s"
  613. **/
  614. ripng_if_down(ifp);
  615. ripng_connect_set (ifp, 0);
  616. }
  617. }
  618. }
  619. /* Set distribute list to all interfaces. */
  620. static void
  621. ripng_enable_apply_all (void)
  622. {
  623. struct interface *ifp;
  624. struct listnode *node;
  625. for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
  626. ripng_enable_apply (ifp);
  627. }
  628. /* Clear all network and neighbor configuration */
  629. void
  630. ripng_clean_network ()
  631. {
  632. unsigned int i;
  633. char *str;
  634. struct route_node *rn;
  635. /* ripng_enable_network */
  636. for (rn = route_top (ripng_enable_network); rn; rn = route_next (rn))
  637. if (rn->info) {
  638. rn->info = NULL;
  639. route_unlock_node(rn);
  640. }
  641. /* ripng_enable_if */
  642. for (i = 0; i < vector_active (ripng_enable_if); i++)
  643. if ((str = vector_slot (ripng_enable_if, i)) != NULL) {
  644. free (str);
  645. vector_slot (ripng_enable_if, i) = NULL;
  646. }
  647. }
  648. /* Vector to store passive-interface name. */
  649. vector Vripng_passive_interface;
  650. /* Utility function for looking up passive interface settings. */
  651. static int
  652. ripng_passive_interface_lookup (const char *ifname)
  653. {
  654. unsigned int i;
  655. char *str;
  656. for (i = 0; i < vector_active (Vripng_passive_interface); i++)
  657. if ((str = vector_slot (Vripng_passive_interface, i)) != NULL)
  658. if (strcmp (str, ifname) == 0)
  659. return i;
  660. return -1;
  661. }
  662. void
  663. ripng_passive_interface_apply (struct interface *ifp)
  664. {
  665. int ret;
  666. struct ripng_interface *ri;
  667. ri = ifp->info;
  668. ret = ripng_passive_interface_lookup (ifp->name);
  669. if (ret < 0)
  670. ri->passive = 0;
  671. else
  672. ri->passive = 1;
  673. }
  674. static void
  675. ripng_passive_interface_apply_all (void)
  676. {
  677. struct interface *ifp;
  678. struct listnode *node;
  679. for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
  680. ripng_passive_interface_apply (ifp);
  681. }
  682. /* Passive interface. */
  683. static int
  684. ripng_passive_interface_set (struct vty *vty, const char *ifname)
  685. {
  686. if (ripng_passive_interface_lookup (ifname) >= 0)
  687. return CMD_WARNING;
  688. vector_set (Vripng_passive_interface, strdup (ifname));
  689. ripng_passive_interface_apply_all ();
  690. return CMD_SUCCESS;
  691. }
  692. static int
  693. ripng_passive_interface_unset (struct vty *vty, const char *ifname)
  694. {
  695. int i;
  696. char *str;
  697. i = ripng_passive_interface_lookup (ifname);
  698. if (i < 0)
  699. return CMD_WARNING;
  700. str = vector_slot (Vripng_passive_interface, i);
  701. free (str);
  702. vector_unset (Vripng_passive_interface, i);
  703. ripng_passive_interface_apply_all ();
  704. return CMD_SUCCESS;
  705. }
  706. /* Free all configured RIP passive-interface settings. */
  707. void
  708. ripng_passive_interface_clean (void)
  709. {
  710. unsigned int i;
  711. char *str;
  712. for (i = 0; i < vector_active (Vripng_passive_interface); i++)
  713. if ((str = vector_slot (Vripng_passive_interface, i)) != NULL)
  714. {
  715. free (str);
  716. vector_slot (Vripng_passive_interface, i) = NULL;
  717. }
  718. ripng_passive_interface_apply_all ();
  719. }
  720. /* Write RIPng enable network and interface to the vty. */
  721. int
  722. ripng_network_write (struct vty *vty, int config_mode)
  723. {
  724. unsigned int i;
  725. const char *ifname;
  726. struct route_node *node;
  727. char buf[BUFSIZ];
  728. /* Write enable network. */
  729. for (node = route_top (ripng_enable_network); node; node = route_next (node))
  730. if (node->info)
  731. {
  732. struct prefix *p = &node->p;
  733. vty_out (vty, "%s%s/%d%s",
  734. config_mode ? " network " : " ",
  735. inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ),
  736. p->prefixlen,
  737. VTY_NEWLINE);
  738. }
  739. /* Write enable interface. */
  740. for (i = 0; i < vector_active (ripng_enable_if); i++)
  741. if ((ifname = vector_slot (ripng_enable_if, i)) != NULL)
  742. vty_out (vty, "%s%s%s",
  743. config_mode ? " network " : " ",
  744. ifname,
  745. VTY_NEWLINE);
  746. /* Write passive interface. */
  747. if (config_mode)
  748. for (i = 0; i < vector_active (Vripng_passive_interface); i++)
  749. if ((ifname = vector_slot (Vripng_passive_interface, i)) != NULL)
  750. vty_out (vty, " passive-interface %s%s", ifname, VTY_NEWLINE);
  751. return 0;
  752. }
  753. /* RIPng enable on specified interface or matched network. */
  754. DEFUN (ripng_network,
  755. ripng_network_cmd,
  756. "network IF_OR_ADDR",
  757. "RIPng enable on specified interface or network.\n"
  758. "Interface or address")
  759. {
  760. int ret;
  761. struct prefix p;
  762. ret = str2prefix (argv[0], &p);
  763. /* Given string is IPv6 network or interface name. */
  764. if (ret)
  765. ret = ripng_enable_network_add (&p);
  766. else
  767. ret = ripng_enable_if_add (argv[0]);
  768. if (ret < 0)
  769. {
  770. vty_out (vty, "There is same network configuration %s%s", argv[0],
  771. VTY_NEWLINE);
  772. return CMD_WARNING;
  773. }
  774. return CMD_SUCCESS;
  775. }
  776. /* RIPng enable on specified interface or matched network. */
  777. DEFUN (no_ripng_network,
  778. no_ripng_network_cmd,
  779. "no network IF_OR_ADDR",
  780. NO_STR
  781. "RIPng enable on specified interface or network.\n"
  782. "Interface or address")
  783. {
  784. int ret;
  785. struct prefix p;
  786. ret = str2prefix (argv[0], &p);
  787. /* Given string is interface name. */
  788. if (ret)
  789. ret = ripng_enable_network_delete (&p);
  790. else
  791. ret = ripng_enable_if_delete (argv[0]);
  792. if (ret < 0)
  793. {
  794. vty_out (vty, "can't find network %s%s", argv[0],
  795. VTY_NEWLINE);
  796. return CMD_WARNING;
  797. }
  798. return CMD_SUCCESS;
  799. }
  800. DEFUN (ipv6_ripng_split_horizon,
  801. ipv6_ripng_split_horizon_cmd,
  802. "ipv6 ripng split-horizon",
  803. IPV6_STR
  804. "Routing Information Protocol\n"
  805. "Perform split horizon\n")
  806. {
  807. struct interface *ifp;
  808. struct ripng_interface *ri;
  809. ifp = vty->index;
  810. ri = ifp->info;
  811. ri->split_horizon = RIPNG_SPLIT_HORIZON;
  812. return CMD_SUCCESS;
  813. }
  814. DEFUN (ipv6_ripng_split_horizon_poisoned_reverse,
  815. ipv6_ripng_split_horizon_poisoned_reverse_cmd,
  816. "ipv6 ripng split-horizon poisoned-reverse",
  817. IPV6_STR
  818. "Routing Information Protocol\n"
  819. "Perform split horizon\n"
  820. "With poisoned-reverse\n")
  821. {
  822. struct interface *ifp;
  823. struct ripng_interface *ri;
  824. ifp = vty->index;
  825. ri = ifp->info;
  826. ri->split_horizon = RIPNG_SPLIT_HORIZON_POISONED_REVERSE;
  827. return CMD_SUCCESS;
  828. }
  829. DEFUN (no_ipv6_ripng_split_horizon,
  830. no_ipv6_ripng_split_horizon_cmd,
  831. "no ipv6 ripng split-horizon",
  832. NO_STR
  833. IPV6_STR
  834. "Routing Information Protocol\n"
  835. "Perform split horizon\n")
  836. {
  837. struct interface *ifp;
  838. struct ripng_interface *ri;
  839. ifp = vty->index;
  840. ri = ifp->info;
  841. ri->split_horizon = RIPNG_NO_SPLIT_HORIZON;
  842. return CMD_SUCCESS;
  843. }
  844. ALIAS (no_ipv6_ripng_split_horizon,
  845. no_ipv6_ripng_split_horizon_poisoned_reverse_cmd,
  846. "no ipv6 ripng split-horizon poisoned-reverse",
  847. NO_STR
  848. IPV6_STR
  849. "Routing Information Protocol\n"
  850. "Perform split horizon\n"
  851. "With poisoned-reverse\n")
  852. DEFUN (ripng_passive_interface,
  853. ripng_passive_interface_cmd,
  854. "passive-interface IFNAME",
  855. "Suppress routing updates on an interface\n"
  856. "Interface name\n")
  857. {
  858. return ripng_passive_interface_set (vty, argv[0]);
  859. }
  860. DEFUN (no_ripng_passive_interface,
  861. no_ripng_passive_interface_cmd,
  862. "no passive-interface IFNAME",
  863. NO_STR
  864. "Suppress routing updates on an interface\n"
  865. "Interface name\n")
  866. {
  867. return ripng_passive_interface_unset (vty, argv[0]);
  868. }
  869. static struct ripng_interface *
  870. ri_new (void)
  871. {
  872. struct ripng_interface *ri;
  873. ri = XCALLOC (MTYPE_IF, sizeof (struct ripng_interface));
  874. /* Set default split-horizon behavior. If the interface is Frame
  875. Relay or SMDS is enabled, the default value for split-horizon is
  876. off. But currently Zebra does detect Frame Relay or SMDS
  877. interface. So all interface is set to split horizon. */
  878. ri->split_horizon_default = RIPNG_SPLIT_HORIZON;
  879. ri->split_horizon = ri->split_horizon_default;
  880. return ri;
  881. }
  882. static int
  883. ripng_if_new_hook (struct interface *ifp)
  884. {
  885. ifp->info = ri_new ();
  886. return 0;
  887. }
  888. /* Called when interface structure deleted. */
  889. static int
  890. ripng_if_delete_hook (struct interface *ifp)
  891. {
  892. XFREE (MTYPE_IF, ifp->info);
  893. ifp->info = NULL;
  894. return 0;
  895. }
  896. /* Configuration write function for ripngd. */
  897. static int
  898. interface_config_write (struct vty *vty)
  899. {
  900. struct listnode *node;
  901. struct interface *ifp;
  902. struct ripng_interface *ri;
  903. int write = 0;
  904. for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
  905. {
  906. ri = ifp->info;
  907. /* Do not display the interface if there is no
  908. * configuration about it.
  909. **/
  910. if ((!ifp->desc) &&
  911. (ri->split_horizon == ri->split_horizon_default))
  912. continue;
  913. vty_out (vty, "interface %s%s", ifp->name,
  914. VTY_NEWLINE);
  915. if (ifp->desc)
  916. vty_out (vty, " description %s%s", ifp->desc,
  917. VTY_NEWLINE);
  918. /* Split horizon. */
  919. if (ri->split_horizon != ri->split_horizon_default)
  920. {
  921. switch (ri->split_horizon) {
  922. case RIPNG_SPLIT_HORIZON:
  923. vty_out (vty, " ipv6 ripng split-horizon%s", VTY_NEWLINE);
  924. break;
  925. case RIPNG_SPLIT_HORIZON_POISONED_REVERSE:
  926. vty_out (vty, " ipv6 ripng split-horizon poisoned-reverse%s",
  927. VTY_NEWLINE);
  928. break;
  929. case RIPNG_NO_SPLIT_HORIZON:
  930. default:
  931. vty_out (vty, " no ipv6 ripng split-horizon%s", VTY_NEWLINE);
  932. break;
  933. }
  934. }
  935. vty_out (vty, "!%s", VTY_NEWLINE);
  936. write++;
  937. }
  938. return write;
  939. }
  940. /* ripngd's interface node. */
  941. static struct cmd_node interface_node =
  942. {
  943. INTERFACE_NODE,
  944. "%s(config-if)# ",
  945. 1 /* VTYSH */
  946. };
  947. /* Initialization of interface. */
  948. void
  949. ripng_if_init ()
  950. {
  951. /* Interface initialize. */
  952. iflist = list_new ();
  953. if_add_hook (IF_NEW_HOOK, ripng_if_new_hook);
  954. if_add_hook (IF_DELETE_HOOK, ripng_if_delete_hook);
  955. /* RIPng enable network init. */
  956. ripng_enable_network = route_table_init ();
  957. /* RIPng enable interface init. */
  958. ripng_enable_if = vector_init (1);
  959. /* RIPng passive interface. */
  960. Vripng_passive_interface = vector_init (1);
  961. /* Install interface node. */
  962. install_node (&interface_node, interface_config_write);
  963. /* Install commands. */
  964. install_element (CONFIG_NODE, &interface_cmd);
  965. install_element (CONFIG_NODE, &no_interface_cmd);
  966. install_default (INTERFACE_NODE);
  967. install_element (INTERFACE_NODE, &interface_desc_cmd);
  968. install_element (INTERFACE_NODE, &no_interface_desc_cmd);
  969. install_element (RIPNG_NODE, &ripng_network_cmd);
  970. install_element (RIPNG_NODE, &no_ripng_network_cmd);
  971. install_element (RIPNG_NODE, &ripng_passive_interface_cmd);
  972. install_element (RIPNG_NODE, &no_ripng_passive_interface_cmd);
  973. install_element (INTERFACE_NODE, &ipv6_ripng_split_horizon_cmd);
  974. install_element (INTERFACE_NODE, &ipv6_ripng_split_horizon_poisoned_reverse_cmd);
  975. install_element (INTERFACE_NODE, &no_ipv6_ripng_split_horizon_cmd);
  976. install_element (INTERFACE_NODE, &no_ipv6_ripng_split_horizon_poisoned_reverse_cmd);
  977. }