ripng_interface.c 29 KB

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