ripng_interface.c 29 KB

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